OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [tracepoint.c] - Diff between revs 105 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 105 Rev 1765
/* Tracing functionality for remote targets in custom GDB protocol
/* Tracing functionality for remote targets in custom GDB protocol
   Copyright 1997, 1998 Free Software Foundation, Inc.
   Copyright 1997, 1998 Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
   Boston, MA 02111-1307, USA.  */
 
 
#include "defs.h"
#include "defs.h"
#include "symtab.h"
#include "symtab.h"
#include "frame.h"
#include "frame.h"
#include "gdbtypes.h"
#include "gdbtypes.h"
#include "expression.h"
#include "expression.h"
#include "gdbcmd.h"
#include "gdbcmd.h"
#include "value.h"
#include "value.h"
#include "target.h"
#include "target.h"
#include "language.h"
#include "language.h"
#include "gdb_string.h"
#include "gdb_string.h"
#include "inferior.h"
#include "inferior.h"
#include "tracepoint.h"
#include "tracepoint.h"
#include "remote.h"
#include "remote.h"
 
 
#include "ax.h"
#include "ax.h"
#include "ax-gdb.h"
#include "ax-gdb.h"
 
 
/* readline include files */
/* readline include files */
#include <readline/readline.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <readline/history.h>
 
 
/* readline defines this.  */
/* readline defines this.  */
#undef savestring
#undef savestring
 
 
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <unistd.h>
#endif
#endif
 
 
/* maximum length of an agent aexpression.
/* maximum length of an agent aexpression.
   this accounts for the fact that packets are limited to 400 bytes
   this accounts for the fact that packets are limited to 400 bytes
   (which includes everything -- including the checksum), and assumes
   (which includes everything -- including the checksum), and assumes
   the worst case of maximum length for each of the pieces of a
   the worst case of maximum length for each of the pieces of a
   continuation packet.
   continuation packet.
 
 
   NOTE: expressions get mem2hex'ed otherwise this would be twice as
   NOTE: expressions get mem2hex'ed otherwise this would be twice as
   large.  (400 - 31)/2 == 184 */
   large.  (400 - 31)/2 == 184 */
#define MAX_AGENT_EXPR_LEN      184
#define MAX_AGENT_EXPR_LEN      184
 
 
 
 
extern int info_verbose;
extern int info_verbose;
extern void (*readline_begin_hook) PARAMS ((char *,...));
extern void (*readline_begin_hook) PARAMS ((char *,...));
extern char *(*readline_hook) PARAMS ((char *));
extern char *(*readline_hook) PARAMS ((char *));
extern void (*readline_end_hook) PARAMS ((void));
extern void (*readline_end_hook) PARAMS ((void));
extern void x_command PARAMS ((char *, int));
extern void x_command PARAMS ((char *, int));
extern int addressprint;        /* Print machine addresses? */
extern int addressprint;        /* Print machine addresses? */
 
 
/* GDB commands implemented in other modules:
/* GDB commands implemented in other modules:
 */
 */
 
 
extern void output_command PARAMS ((char *, int));
extern void output_command PARAMS ((char *, int));
extern void registers_info PARAMS ((char *, int));
extern void registers_info PARAMS ((char *, int));
extern void args_info      PARAMS ((char *, int));
extern void args_info      PARAMS ((char *, int));
extern void locals_info    PARAMS ((char *, int));
extern void locals_info    PARAMS ((char *, int));
 
 
 
 
/* If this definition isn't overridden by the header files, assume
/* If this definition isn't overridden by the header files, assume
   that isatty and fileno exist on this system.  */
   that isatty and fileno exist on this system.  */
#ifndef ISATTY
#ifndef ISATTY
#define ISATTY(FP)      (isatty (fileno (FP)))
#define ISATTY(FP)      (isatty (fileno (FP)))
#endif
#endif
 
 
/*
/*
   Tracepoint.c:
   Tracepoint.c:
 
 
   This module defines the following debugger commands:
   This module defines the following debugger commands:
   trace            : set a tracepoint on a function, line, or address.
   trace            : set a tracepoint on a function, line, or address.
   info trace       : list all debugger-defined tracepoints.
   info trace       : list all debugger-defined tracepoints.
   delete trace     : delete one or more tracepoints.
   delete trace     : delete one or more tracepoints.
   enable trace     : enable one or more tracepoints.
   enable trace     : enable one or more tracepoints.
   disable trace    : disable one or more tracepoints.
   disable trace    : disable one or more tracepoints.
   actions          : specify actions to be taken at a tracepoint.
   actions          : specify actions to be taken at a tracepoint.
   passcount        : specify a pass count for a tracepoint.
   passcount        : specify a pass count for a tracepoint.
   tstart           : start a trace experiment.
   tstart           : start a trace experiment.
   tstop            : stop a trace experiment.
   tstop            : stop a trace experiment.
   tstatus          : query the status of a trace experiment.
   tstatus          : query the status of a trace experiment.
   tfind            : find a trace frame in the trace buffer.
   tfind            : find a trace frame in the trace buffer.
   tdump            : print everything collected at the current tracepoint.
   tdump            : print everything collected at the current tracepoint.
   save-tracepoints : write tracepoint setup into a file.
   save-tracepoints : write tracepoint setup into a file.
 
 
   This module defines the following user-visible debugger variables:
   This module defines the following user-visible debugger variables:
   $trace_frame : sequence number of trace frame currently being debugged.
   $trace_frame : sequence number of trace frame currently being debugged.
   $trace_line  : source line of trace frame currently being debugged.
   $trace_line  : source line of trace frame currently being debugged.
   $trace_file  : source file of trace frame currently being debugged.
   $trace_file  : source file of trace frame currently being debugged.
   $tracepoint  : tracepoint number of trace frame currently being debugged.
   $tracepoint  : tracepoint number of trace frame currently being debugged.
 */
 */
 
 
 
 
/* ======= Important global variables: ======= */
/* ======= Important global variables: ======= */
 
 
/* Chain of all tracepoints defined.  */
/* Chain of all tracepoints defined.  */
struct tracepoint *tracepoint_chain;
struct tracepoint *tracepoint_chain;
 
 
/* Number of last tracepoint made.  */
/* Number of last tracepoint made.  */
static int tracepoint_count;
static int tracepoint_count;
 
 
/* Number of last traceframe collected.  */
/* Number of last traceframe collected.  */
static int traceframe_number;
static int traceframe_number;
 
 
/* Tracepoint for last traceframe collected.  */
/* Tracepoint for last traceframe collected.  */
static int tracepoint_number;
static int tracepoint_number;
 
 
/* Symbol for function for last traceframe collected */
/* Symbol for function for last traceframe collected */
static struct symbol *traceframe_fun;
static struct symbol *traceframe_fun;
 
 
/* Symtab and line for last traceframe collected */
/* Symtab and line for last traceframe collected */
static struct symtab_and_line traceframe_sal;
static struct symtab_and_line traceframe_sal;
 
 
/* Tracing command lists */
/* Tracing command lists */
static struct cmd_list_element *tfindlist;
static struct cmd_list_element *tfindlist;
 
 
/* ======= Important command functions: ======= */
/* ======= Important command functions: ======= */
static void trace_command PARAMS ((char *, int));
static void trace_command PARAMS ((char *, int));
static void tracepoints_info PARAMS ((char *, int));
static void tracepoints_info PARAMS ((char *, int));
static void delete_trace_command PARAMS ((char *, int));
static void delete_trace_command PARAMS ((char *, int));
static void enable_trace_command PARAMS ((char *, int));
static void enable_trace_command PARAMS ((char *, int));
static void disable_trace_command PARAMS ((char *, int));
static void disable_trace_command PARAMS ((char *, int));
static void trace_pass_command PARAMS ((char *, int));
static void trace_pass_command PARAMS ((char *, int));
static void trace_actions_command PARAMS ((char *, int));
static void trace_actions_command PARAMS ((char *, int));
static void trace_start_command PARAMS ((char *, int));
static void trace_start_command PARAMS ((char *, int));
static void trace_stop_command PARAMS ((char *, int));
static void trace_stop_command PARAMS ((char *, int));
static void trace_status_command PARAMS ((char *, int));
static void trace_status_command PARAMS ((char *, int));
static void trace_find_command PARAMS ((char *, int));
static void trace_find_command PARAMS ((char *, int));
static void trace_find_pc_command PARAMS ((char *, int));
static void trace_find_pc_command PARAMS ((char *, int));
static void trace_find_tracepoint_command PARAMS ((char *, int));
static void trace_find_tracepoint_command PARAMS ((char *, int));
static void trace_find_line_command PARAMS ((char *, int));
static void trace_find_line_command PARAMS ((char *, int));
static void trace_find_range_command PARAMS ((char *, int));
static void trace_find_range_command PARAMS ((char *, int));
static void trace_find_outside_command PARAMS ((char *, int));
static void trace_find_outside_command PARAMS ((char *, int));
static void tracepoint_save_command PARAMS ((char *, int));
static void tracepoint_save_command PARAMS ((char *, int));
static void trace_dump_command PARAMS ((char *, int));
static void trace_dump_command PARAMS ((char *, int));
 
 
/* support routines */
/* support routines */
static void trace_mention PARAMS ((struct tracepoint *));
static void trace_mention PARAMS ((struct tracepoint *));
 
 
struct collection_list;
struct collection_list;
static void add_aexpr PARAMS ((struct collection_list *, struct agent_expr *));
static void add_aexpr PARAMS ((struct collection_list *, struct agent_expr *));
static unsigned char *mem2hex (unsigned char *, unsigned char *, int);
static unsigned char *mem2hex (unsigned char *, unsigned char *, int);
static void add_register PARAMS ((struct collection_list * collection,
static void add_register PARAMS ((struct collection_list * collection,
                                  unsigned int regno));
                                  unsigned int regno));
static void free_actions_list PARAMS ((char **actions_list));
static void free_actions_list PARAMS ((char **actions_list));
static void free_actions_list_cleanup_wrapper PARAMS ((void *));
static void free_actions_list_cleanup_wrapper PARAMS ((void *));
 
 
extern void _initialize_tracepoint PARAMS ((void));
extern void _initialize_tracepoint PARAMS ((void));
 
 
/* Utility: returns true if "target remote" */
/* Utility: returns true if "target remote" */
static int
static int
target_is_remote ()
target_is_remote ()
{
{
  if (current_target.to_shortname &&
  if (current_target.to_shortname &&
      strcmp (current_target.to_shortname, "remote") == 0)
      strcmp (current_target.to_shortname, "remote") == 0)
    return 1;
    return 1;
  else
  else
    return 0;
    return 0;
}
}
 
 
/* Utility: generate error from an incoming stub packet.  */
/* Utility: generate error from an incoming stub packet.  */
static void
static void
trace_error (buf)
trace_error (buf)
     char *buf;
     char *buf;
{
{
  if (*buf++ != 'E')
  if (*buf++ != 'E')
    return;                     /* not an error msg */
    return;                     /* not an error msg */
  switch (*buf)
  switch (*buf)
    {
    {
    case '1':                   /* malformed packet error */
    case '1':                   /* malformed packet error */
      if (*++buf == '0')        /*   general case: */
      if (*++buf == '0')        /*   general case: */
        error ("tracepoint.c: error in outgoing packet.");
        error ("tracepoint.c: error in outgoing packet.");
      else
      else
        error ("tracepoint.c: error in outgoing packet at field #%d.",
        error ("tracepoint.c: error in outgoing packet at field #%d.",
               strtol (buf, NULL, 16));
               strtol (buf, NULL, 16));
    case '2':
    case '2':
      error ("trace API error 0x%s.", ++buf);
      error ("trace API error 0x%s.", ++buf);
    default:
    default:
      error ("Target returns error code '%s'.", buf);
      error ("Target returns error code '%s'.", buf);
    }
    }
}
}
 
 
/* Utility: wait for reply from stub, while accepting "O" packets */
/* Utility: wait for reply from stub, while accepting "O" packets */
static char *
static char *
remote_get_noisy_reply (char *buf,
remote_get_noisy_reply (char *buf,
                        long sizeof_buf)
                        long sizeof_buf)
{
{
  do                            /* loop on reply from remote stub */
  do                            /* loop on reply from remote stub */
    {
    {
      QUIT;                     /* allow user to bail out with ^C */
      QUIT;                     /* allow user to bail out with ^C */
      getpkt (buf, sizeof_buf, 0);
      getpkt (buf, sizeof_buf, 0);
      if (buf[0] == 0)
      if (buf[0] == 0)
        error ("Target does not support this command.");
        error ("Target does not support this command.");
      else if (buf[0] == 'E')
      else if (buf[0] == 'E')
        trace_error (buf);
        trace_error (buf);
      else if (buf[0] == 'O' &&
      else if (buf[0] == 'O' &&
               buf[1] != 'K')
               buf[1] != 'K')
        remote_console_output (buf + 1);        /* 'O' message from stub */
        remote_console_output (buf + 1);        /* 'O' message from stub */
      else
      else
        return buf;             /* here's the actual reply */
        return buf;             /* here's the actual reply */
    }
    }
  while (1);
  while (1);
}
}
 
 
/* Set tracepoint count to NUM.  */
/* Set tracepoint count to NUM.  */
static void
static void
set_tracepoint_count (num)
set_tracepoint_count (num)
     int num;
     int num;
{
{
  tracepoint_count = num;
  tracepoint_count = num;
  set_internalvar (lookup_internalvar ("tpnum"),
  set_internalvar (lookup_internalvar ("tpnum"),
                   value_from_longest (builtin_type_int, (LONGEST) num));
                   value_from_longest (builtin_type_int, (LONGEST) num));
}
}
 
 
/* Set traceframe number to NUM.  */
/* Set traceframe number to NUM.  */
static void
static void
set_traceframe_num (num)
set_traceframe_num (num)
     int num;
     int num;
{
{
  traceframe_number = num;
  traceframe_number = num;
  set_internalvar (lookup_internalvar ("trace_frame"),
  set_internalvar (lookup_internalvar ("trace_frame"),
                   value_from_longest (builtin_type_int, (LONGEST) num));
                   value_from_longest (builtin_type_int, (LONGEST) num));
}
}
 
 
/* Set tracepoint number to NUM.  */
/* Set tracepoint number to NUM.  */
static void
static void
set_tracepoint_num (num)
set_tracepoint_num (num)
     int num;
     int num;
{
{
  tracepoint_number = num;
  tracepoint_number = num;
  set_internalvar (lookup_internalvar ("tracepoint"),
  set_internalvar (lookup_internalvar ("tracepoint"),
                   value_from_longest (builtin_type_int, (LONGEST) num));
                   value_from_longest (builtin_type_int, (LONGEST) num));
}
}
 
 
/* Set externally visible debug variables for querying/printing
/* Set externally visible debug variables for querying/printing
   the traceframe context (line, function, file) */
   the traceframe context (line, function, file) */
 
 
static void
static void
set_traceframe_context (trace_pc)
set_traceframe_context (trace_pc)
     CORE_ADDR trace_pc;
     CORE_ADDR trace_pc;
{
{
  static struct type *func_string, *file_string;
  static struct type *func_string, *file_string;
  static struct type *func_range, *file_range;
  static struct type *func_range, *file_range;
  static value_ptr func_val, file_val;
  static value_ptr func_val, file_val;
  static struct type *charstar;
  static struct type *charstar;
  int len;
  int len;
 
 
  if (charstar == (struct type *) NULL)
  if (charstar == (struct type *) NULL)
    charstar = lookup_pointer_type (builtin_type_char);
    charstar = lookup_pointer_type (builtin_type_char);
 
 
  if (trace_pc == -1)           /* cease debugging any trace buffers */
  if (trace_pc == -1)           /* cease debugging any trace buffers */
    {
    {
      traceframe_fun = 0;
      traceframe_fun = 0;
      traceframe_sal.pc = traceframe_sal.line = 0;
      traceframe_sal.pc = traceframe_sal.line = 0;
      traceframe_sal.symtab = NULL;
      traceframe_sal.symtab = NULL;
      set_internalvar (lookup_internalvar ("trace_func"),
      set_internalvar (lookup_internalvar ("trace_func"),
                       value_from_longest (charstar, (LONGEST) 0));
                       value_from_longest (charstar, (LONGEST) 0));
      set_internalvar (lookup_internalvar ("trace_file"),
      set_internalvar (lookup_internalvar ("trace_file"),
                       value_from_longest (charstar, (LONGEST) 0));
                       value_from_longest (charstar, (LONGEST) 0));
      set_internalvar (lookup_internalvar ("trace_line"),
      set_internalvar (lookup_internalvar ("trace_line"),
                       value_from_longest (builtin_type_int, (LONGEST) - 1));
                       value_from_longest (builtin_type_int, (LONGEST) - 1));
      return;
      return;
    }
    }
 
 
  /* save as globals for internal use */
  /* save as globals for internal use */
  traceframe_sal = find_pc_line (trace_pc, 0);
  traceframe_sal = find_pc_line (trace_pc, 0);
  traceframe_fun = find_pc_function (trace_pc);
  traceframe_fun = find_pc_function (trace_pc);
 
 
  /* save linenumber as "$trace_line", a debugger variable visible to users */
  /* save linenumber as "$trace_line", a debugger variable visible to users */
  set_internalvar (lookup_internalvar ("trace_line"),
  set_internalvar (lookup_internalvar ("trace_line"),
                   value_from_longest (builtin_type_int,
                   value_from_longest (builtin_type_int,
                                       (LONGEST) traceframe_sal.line));
                                       (LONGEST) traceframe_sal.line));
 
 
  /* save func name as "$trace_func", a debugger variable visible to users */
  /* save func name as "$trace_func", a debugger variable visible to users */
  if (traceframe_fun == NULL ||
  if (traceframe_fun == NULL ||
      SYMBOL_NAME (traceframe_fun) == NULL)
      SYMBOL_NAME (traceframe_fun) == NULL)
    set_internalvar (lookup_internalvar ("trace_func"),
    set_internalvar (lookup_internalvar ("trace_func"),
                     value_from_longest (charstar, (LONGEST) 0));
                     value_from_longest (charstar, (LONGEST) 0));
  else
  else
    {
    {
      len = strlen (SYMBOL_NAME (traceframe_fun));
      len = strlen (SYMBOL_NAME (traceframe_fun));
      func_range = create_range_type (func_range,
      func_range = create_range_type (func_range,
                                      builtin_type_int, 0, len - 1);
                                      builtin_type_int, 0, len - 1);
      func_string = create_array_type (func_string,
      func_string = create_array_type (func_string,
                                       builtin_type_char, func_range);
                                       builtin_type_char, func_range);
      func_val = allocate_value (func_string);
      func_val = allocate_value (func_string);
      VALUE_TYPE (func_val) = func_string;
      VALUE_TYPE (func_val) = func_string;
      memcpy (VALUE_CONTENTS_RAW (func_val),
      memcpy (VALUE_CONTENTS_RAW (func_val),
              SYMBOL_NAME (traceframe_fun),
              SYMBOL_NAME (traceframe_fun),
              len);
              len);
      func_val->modifiable = 0;
      func_val->modifiable = 0;
      set_internalvar (lookup_internalvar ("trace_func"), func_val);
      set_internalvar (lookup_internalvar ("trace_func"), func_val);
    }
    }
 
 
  /* save file name as "$trace_file", a debugger variable visible to users */
  /* save file name as "$trace_file", a debugger variable visible to users */
  if (traceframe_sal.symtab == NULL ||
  if (traceframe_sal.symtab == NULL ||
      traceframe_sal.symtab->filename == NULL)
      traceframe_sal.symtab->filename == NULL)
    set_internalvar (lookup_internalvar ("trace_file"),
    set_internalvar (lookup_internalvar ("trace_file"),
                     value_from_longest (charstar, (LONGEST) 0));
                     value_from_longest (charstar, (LONGEST) 0));
  else
  else
    {
    {
      len = strlen (traceframe_sal.symtab->filename);
      len = strlen (traceframe_sal.symtab->filename);
      file_range = create_range_type (file_range,
      file_range = create_range_type (file_range,
                                      builtin_type_int, 0, len - 1);
                                      builtin_type_int, 0, len - 1);
      file_string = create_array_type (file_string,
      file_string = create_array_type (file_string,
                                       builtin_type_char, file_range);
                                       builtin_type_char, file_range);
      file_val = allocate_value (file_string);
      file_val = allocate_value (file_string);
      VALUE_TYPE (file_val) = file_string;
      VALUE_TYPE (file_val) = file_string;
      memcpy (VALUE_CONTENTS_RAW (file_val),
      memcpy (VALUE_CONTENTS_RAW (file_val),
              traceframe_sal.symtab->filename,
              traceframe_sal.symtab->filename,
              len);
              len);
      file_val->modifiable = 0;
      file_val->modifiable = 0;
      set_internalvar (lookup_internalvar ("trace_file"), file_val);
      set_internalvar (lookup_internalvar ("trace_file"), file_val);
    }
    }
}
}
 
 
/* Low level routine to set a tracepoint.
/* Low level routine to set a tracepoint.
   Returns the tracepoint object so caller can set other things.
   Returns the tracepoint object so caller can set other things.
   Does not set the tracepoint number!
   Does not set the tracepoint number!
   Does not print anything.
   Does not print anything.
 
 
   ==> This routine should not be called if there is a chance of later
   ==> This routine should not be called if there is a chance of later
   error(); otherwise it leaves a bogus tracepoint on the chain.  Validate
   error(); otherwise it leaves a bogus tracepoint on the chain.  Validate
   your arguments BEFORE calling this routine!  */
   your arguments BEFORE calling this routine!  */
 
 
static struct tracepoint *
static struct tracepoint *
set_raw_tracepoint (sal)
set_raw_tracepoint (sal)
     struct symtab_and_line sal;
     struct symtab_and_line sal;
{
{
  register struct tracepoint *t, *tc;
  register struct tracepoint *t, *tc;
  struct cleanup *old_chain;
  struct cleanup *old_chain;
 
 
  t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
  t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
  old_chain = make_cleanup (free, t);
  old_chain = make_cleanup (free, t);
  memset (t, 0, sizeof (*t));
  memset (t, 0, sizeof (*t));
  t->address = sal.pc;
  t->address = sal.pc;
  if (sal.symtab == NULL)
  if (sal.symtab == NULL)
    t->source_file = NULL;
    t->source_file = NULL;
  else
  else
    t->source_file = savestring (sal.symtab->filename,
    t->source_file = savestring (sal.symtab->filename,
                                 strlen (sal.symtab->filename));
                                 strlen (sal.symtab->filename));
 
 
  t->section = sal.section;
  t->section = sal.section;
  t->language = current_language->la_language;
  t->language = current_language->la_language;
  t->input_radix = input_radix;
  t->input_radix = input_radix;
  t->line_number = sal.line;
  t->line_number = sal.line;
  t->enabled = enabled;
  t->enabled = enabled;
  t->next = 0;
  t->next = 0;
  t->step_count = 0;
  t->step_count = 0;
  t->pass_count = 0;
  t->pass_count = 0;
  t->addr_string = NULL;
  t->addr_string = NULL;
 
 
  /* Add this tracepoint to the end of the chain
  /* Add this tracepoint to the end of the chain
     so that a list of tracepoints will come out in order
     so that a list of tracepoints will come out in order
     of increasing numbers.  */
     of increasing numbers.  */
 
 
  tc = tracepoint_chain;
  tc = tracepoint_chain;
  if (tc == 0)
  if (tc == 0)
    tracepoint_chain = t;
    tracepoint_chain = t;
  else
  else
    {
    {
      while (tc->next)
      while (tc->next)
        tc = tc->next;
        tc = tc->next;
      tc->next = t;
      tc->next = t;
    }
    }
  discard_cleanups (old_chain);
  discard_cleanups (old_chain);
  return t;
  return t;
}
}
 
 
/* Set a tracepoint according to ARG (function, linenum or *address) */
/* Set a tracepoint according to ARG (function, linenum or *address) */
static void
static void
trace_command (arg, from_tty)
trace_command (arg, from_tty)
     char *arg;
     char *arg;
     int from_tty;
     int from_tty;
{
{
  char **canonical = (char **) NULL;
  char **canonical = (char **) NULL;
  struct symtabs_and_lines sals;
  struct symtabs_and_lines sals;
  struct symtab_and_line sal;
  struct symtab_and_line sal;
  struct tracepoint *t;
  struct tracepoint *t;
  char *addr_start = 0, *addr_end = 0;
  char *addr_start = 0, *addr_end = 0;
  int i;
  int i;
 
 
  if (!arg || !*arg)
  if (!arg || !*arg)
    error ("trace command requires an argument");
    error ("trace command requires an argument");
 
 
  if (from_tty && info_verbose)
  if (from_tty && info_verbose)
    printf_filtered ("TRACE %s\n", arg);
    printf_filtered ("TRACE %s\n", arg);
 
 
  addr_start = arg;
  addr_start = arg;
  sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, &canonical);
  sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, &canonical);
  addr_end = arg;
  addr_end = arg;
  if (!sals.nelts)
  if (!sals.nelts)
    return;                     /* ??? Presumably decode_line_1 has already warned? */
    return;                     /* ??? Presumably decode_line_1 has already warned? */
 
 
  /* Resolve all line numbers to PC's */
  /* Resolve all line numbers to PC's */
  for (i = 0; i < sals.nelts; i++)
  for (i = 0; i < sals.nelts; i++)
    resolve_sal_pc (&sals.sals[i]);
    resolve_sal_pc (&sals.sals[i]);
 
 
  /* Now set all the tracepoints.  */
  /* Now set all the tracepoints.  */
  for (i = 0; i < sals.nelts; i++)
  for (i = 0; i < sals.nelts; i++)
    {
    {
      sal = sals.sals[i];
      sal = sals.sals[i];
 
 
      t = set_raw_tracepoint (sal);
      t = set_raw_tracepoint (sal);
      set_tracepoint_count (tracepoint_count + 1);
      set_tracepoint_count (tracepoint_count + 1);
      t->number = tracepoint_count;
      t->number = tracepoint_count;
 
 
      /* If a canonical line spec is needed use that instead of the
      /* If a canonical line spec is needed use that instead of the
         command string.  */
         command string.  */
      if (canonical != (char **) NULL && canonical[i] != NULL)
      if (canonical != (char **) NULL && canonical[i] != NULL)
        t->addr_string = canonical[i];
        t->addr_string = canonical[i];
      else if (addr_start)
      else if (addr_start)
        t->addr_string = savestring (addr_start, addr_end - addr_start);
        t->addr_string = savestring (addr_start, addr_end - addr_start);
 
 
      trace_mention (t);
      trace_mention (t);
 
 
      /* Let the UI know of any additions */
      /* Let the UI know of any additions */
      if (create_tracepoint_hook)
      if (create_tracepoint_hook)
        create_tracepoint_hook (t);
        create_tracepoint_hook (t);
    }
    }
 
 
  if (sals.nelts > 1)
  if (sals.nelts > 1)
    {
    {
      printf_filtered ("Multiple tracepoints were set.\n");
      printf_filtered ("Multiple tracepoints were set.\n");
      printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
      printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
    }
    }
}
}
 
 
/* Tell the user we have just set a tracepoint TP. */
/* Tell the user we have just set a tracepoint TP. */
 
 
static void
static void
trace_mention (tp)
trace_mention (tp)
     struct tracepoint *tp;
     struct tracepoint *tp;
{
{
  printf_filtered ("Tracepoint %d", tp->number);
  printf_filtered ("Tracepoint %d", tp->number);
 
 
  if (addressprint || (tp->source_file == NULL))
  if (addressprint || (tp->source_file == NULL))
    {
    {
      printf_filtered (" at ");
      printf_filtered (" at ");
      print_address_numeric (tp->address, 1, gdb_stdout);
      print_address_numeric (tp->address, 1, gdb_stdout);
    }
    }
  if (tp->source_file)
  if (tp->source_file)
    printf_filtered (": file %s, line %d.",
    printf_filtered (": file %s, line %d.",
                     tp->source_file, tp->line_number);
                     tp->source_file, tp->line_number);
 
 
  printf_filtered ("\n");
  printf_filtered ("\n");
}
}
 
 
/* Print information on tracepoint number TPNUM_EXP, or all if omitted.  */
/* Print information on tracepoint number TPNUM_EXP, or all if omitted.  */
 
 
static void
static void
tracepoints_info (tpnum_exp, from_tty)
tracepoints_info (tpnum_exp, from_tty)
     char *tpnum_exp;
     char *tpnum_exp;
     int from_tty;
     int from_tty;
{
{
  struct tracepoint *t;
  struct tracepoint *t;
  struct action_line *action;
  struct action_line *action;
  int found_a_tracepoint = 0;
  int found_a_tracepoint = 0;
  char wrap_indent[80];
  char wrap_indent[80];
  struct symbol *sym;
  struct symbol *sym;
  int tpnum = -1;
  int tpnum = -1;
 
 
  if (tpnum_exp)
  if (tpnum_exp)
    tpnum = parse_and_eval_address (tpnum_exp);
    tpnum = parse_and_eval_address (tpnum_exp);
 
 
  ALL_TRACEPOINTS (t)
  ALL_TRACEPOINTS (t)
    if (tpnum == -1 || tpnum == t->number)
    if (tpnum == -1 || tpnum == t->number)
    {
    {
      extern int addressprint;  /* print machine addresses? */
      extern int addressprint;  /* print machine addresses? */
 
 
      if (!found_a_tracepoint++)
      if (!found_a_tracepoint++)
        {
        {
          printf_filtered ("Num Enb ");
          printf_filtered ("Num Enb ");
          if (addressprint)
          if (addressprint)
            printf_filtered ("Address    ");
            printf_filtered ("Address    ");
          printf_filtered ("PassC StepC What\n");
          printf_filtered ("PassC StepC What\n");
        }
        }
      strcpy (wrap_indent, "                           ");
      strcpy (wrap_indent, "                           ");
      if (addressprint)
      if (addressprint)
        strcat (wrap_indent, "           ");
        strcat (wrap_indent, "           ");
 
 
      printf_filtered ("%-3d %-3s ", t->number,
      printf_filtered ("%-3d %-3s ", t->number,
                       t->enabled == enabled ? "y" : "n");
                       t->enabled == enabled ? "y" : "n");
      if (addressprint)
      if (addressprint)
        printf_filtered ("%s ",
        printf_filtered ("%s ",
                         local_hex_string_custom ((unsigned long) t->address,
                         local_hex_string_custom ((unsigned long) t->address,
                                                  "08l"));
                                                  "08l"));
      printf_filtered ("%-5d %-5ld ", t->pass_count, t->step_count);
      printf_filtered ("%-5d %-5ld ", t->pass_count, t->step_count);
 
 
      if (t->source_file)
      if (t->source_file)
        {
        {
          sym = find_pc_sect_function (t->address, t->section);
          sym = find_pc_sect_function (t->address, t->section);
          if (sym)
          if (sym)
            {
            {
              fputs_filtered ("in ", gdb_stdout);
              fputs_filtered ("in ", gdb_stdout);
              fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
              fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
              wrap_here (wrap_indent);
              wrap_here (wrap_indent);
              fputs_filtered (" at ", gdb_stdout);
              fputs_filtered (" at ", gdb_stdout);
            }
            }
          fputs_filtered (t->source_file, gdb_stdout);
          fputs_filtered (t->source_file, gdb_stdout);
          printf_filtered (":%d", t->line_number);
          printf_filtered (":%d", t->line_number);
        }
        }
      else
      else
        print_address_symbolic (t->address, gdb_stdout, demangle, " ");
        print_address_symbolic (t->address, gdb_stdout, demangle, " ");
 
 
      printf_filtered ("\n");
      printf_filtered ("\n");
      if (t->actions)
      if (t->actions)
        {
        {
          printf_filtered ("  Actions for tracepoint %d: \n", t->number);
          printf_filtered ("  Actions for tracepoint %d: \n", t->number);
          for (action = t->actions; action; action = action->next)
          for (action = t->actions; action; action = action->next)
            {
            {
              printf_filtered ("\t%s\n", action->action);
              printf_filtered ("\t%s\n", action->action);
            }
            }
        }
        }
    }
    }
  if (!found_a_tracepoint)
  if (!found_a_tracepoint)
    {
    {
      if (tpnum == -1)
      if (tpnum == -1)
        printf_filtered ("No tracepoints.\n");
        printf_filtered ("No tracepoints.\n");
      else
      else
        printf_filtered ("No tracepoint number %d.\n", tpnum);
        printf_filtered ("No tracepoint number %d.\n", tpnum);
    }
    }
}
}
 
 
/* Optimization: the code to parse an enable, disable, or delete TP command
/* Optimization: the code to parse an enable, disable, or delete TP command
   is virtually identical except for whether it performs an enable, disable,
   is virtually identical except for whether it performs an enable, disable,
   or delete.  Therefore I've combined them into one function with an opcode.
   or delete.  Therefore I've combined them into one function with an opcode.
 */
 */
enum tracepoint_opcode
enum tracepoint_opcode
{
{
  enable_op,
  enable_op,
  disable_op,
  disable_op,
  delete_op
  delete_op
};
};
 
 
/* This function implements enable, disable and delete commands. */
/* This function implements enable, disable and delete commands. */
static void
static void
tracepoint_operation (t, from_tty, opcode)
tracepoint_operation (t, from_tty, opcode)
     struct tracepoint *t;
     struct tracepoint *t;
     int from_tty;
     int from_tty;
     enum tracepoint_opcode opcode;
     enum tracepoint_opcode opcode;
{
{
  struct tracepoint *t2;
  struct tracepoint *t2;
 
 
  if (t == NULL)        /* no tracepoint operand */
  if (t == NULL)        /* no tracepoint operand */
    return;
    return;
 
 
  switch (opcode)
  switch (opcode)
    {
    {
    case enable_op:
    case enable_op:
      t->enabled = enabled;
      t->enabled = enabled;
      if (modify_tracepoint_hook)
      if (modify_tracepoint_hook)
        modify_tracepoint_hook (t);
        modify_tracepoint_hook (t);
      break;
      break;
    case disable_op:
    case disable_op:
      t->enabled = disabled;
      t->enabled = disabled;
      if (modify_tracepoint_hook)
      if (modify_tracepoint_hook)
        modify_tracepoint_hook (t);
        modify_tracepoint_hook (t);
      break;
      break;
    case delete_op:
    case delete_op:
      if (tracepoint_chain == t)
      if (tracepoint_chain == t)
        tracepoint_chain = t->next;
        tracepoint_chain = t->next;
 
 
      ALL_TRACEPOINTS (t2)
      ALL_TRACEPOINTS (t2)
        if (t2->next == t)
        if (t2->next == t)
        {
        {
          t2->next = t->next;
          t2->next = t->next;
          break;
          break;
        }
        }
 
 
      /* Let the UI know of any deletions */
      /* Let the UI know of any deletions */
      if (delete_tracepoint_hook)
      if (delete_tracepoint_hook)
        delete_tracepoint_hook (t);
        delete_tracepoint_hook (t);
 
 
      if (t->addr_string)
      if (t->addr_string)
        free (t->addr_string);
        free (t->addr_string);
      if (t->source_file)
      if (t->source_file)
        free (t->source_file);
        free (t->source_file);
      if (t->actions)
      if (t->actions)
        free_actions (t);
        free_actions (t);
 
 
      free (t);
      free (t);
      break;
      break;
    }
    }
}
}
 
 
/* Utility: parse a tracepoint number and look it up in the list.
/* Utility: parse a tracepoint number and look it up in the list.
   If MULTI_P is true, there might be a range of tracepoints in ARG.
   If MULTI_P is true, there might be a range of tracepoints in ARG.
   if OPTIONAL_P is true, then if the argument is missing, the most
   if OPTIONAL_P is true, then if the argument is missing, the most
   recent tracepoint (tracepoint_count) is returned.  */
   recent tracepoint (tracepoint_count) is returned.  */
struct tracepoint *
struct tracepoint *
get_tracepoint_by_number (arg, multi_p, optional_p)
get_tracepoint_by_number (arg, multi_p, optional_p)
     char **arg;
     char **arg;
     int multi_p, optional_p;
     int multi_p, optional_p;
{
{
  struct tracepoint *t;
  struct tracepoint *t;
  int tpnum;
  int tpnum;
  char *instring = arg == NULL ? NULL : *arg;
  char *instring = arg == NULL ? NULL : *arg;
 
 
  if (arg == NULL || *arg == NULL || ! **arg)
  if (arg == NULL || *arg == NULL || ! **arg)
    {
    {
      if (optional_p)
      if (optional_p)
        tpnum = tracepoint_count;
        tpnum = tracepoint_count;
      else
      else
        error_no_arg ("tracepoint number");
        error_no_arg ("tracepoint number");
    }
    }
  else
  else
    tpnum = multi_p ? get_number_or_range (arg) : get_number (arg);
    tpnum = multi_p ? get_number_or_range (arg) : get_number (arg);
 
 
  if (tpnum <= 0)
  if (tpnum <= 0)
    {
    {
      if (instring && *instring)
      if (instring && *instring)
        printf_filtered ("bad tracepoint number at or near '%s'\n", instring);
        printf_filtered ("bad tracepoint number at or near '%s'\n", instring);
      else
      else
        printf_filtered ("Tracepoint argument missing and no previous tracepoint\n");
        printf_filtered ("Tracepoint argument missing and no previous tracepoint\n");
      return NULL;
      return NULL;
    }
    }
 
 
  ALL_TRACEPOINTS (t)
  ALL_TRACEPOINTS (t)
    if (t->number == tpnum)
    if (t->number == tpnum)
    {
    {
      return t;
      return t;
    }
    }
 
 
  /* FIXME: if we are in the middle of a range we don't want to give
  /* FIXME: if we are in the middle of a range we don't want to give
     a message.  The current interface to get_number_or_range doesn't
     a message.  The current interface to get_number_or_range doesn't
     allow us to discover this.  */
     allow us to discover this.  */
  printf_unfiltered ("No tracepoint number %d.\n", tpnum);
  printf_unfiltered ("No tracepoint number %d.\n", tpnum);
  return NULL;
  return NULL;
}
}
 
 
/* Utility: parse a list of tracepoint numbers, and call a func for each. */
/* Utility: parse a list of tracepoint numbers, and call a func for each. */
static void
static void
map_args_over_tracepoints (args, from_tty, opcode)
map_args_over_tracepoints (args, from_tty, opcode)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
     enum tracepoint_opcode opcode;
     enum tracepoint_opcode opcode;
{
{
  struct tracepoint *t, *tmp;
  struct tracepoint *t, *tmp;
 
 
  if (args == 0 || *args == 0)    /* do them all */
  if (args == 0 || *args == 0)    /* do them all */
    ALL_TRACEPOINTS_SAFE (t, tmp)
    ALL_TRACEPOINTS_SAFE (t, tmp)
      tracepoint_operation (t, from_tty, opcode);
      tracepoint_operation (t, from_tty, opcode);
  else
  else
    while (*args)
    while (*args)
      {
      {
        QUIT;                   /* give user option to bail out with ^C */
        QUIT;                   /* give user option to bail out with ^C */
        t = get_tracepoint_by_number (&args, 1, 0);
        t = get_tracepoint_by_number (&args, 1, 0);
        tracepoint_operation (t, from_tty, opcode);
        tracepoint_operation (t, from_tty, opcode);
        while (*args == ' ' || *args == '\t')
        while (*args == ' ' || *args == '\t')
          args++;
          args++;
      }
      }
}
}
 
 
/* The 'enable trace' command enables tracepoints.  Not supported by all targets.  */
/* The 'enable trace' command enables tracepoints.  Not supported by all targets.  */
static void
static void
enable_trace_command (args, from_tty)
enable_trace_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  dont_repeat ();
  dont_repeat ();
  map_args_over_tracepoints (args, from_tty, enable_op);
  map_args_over_tracepoints (args, from_tty, enable_op);
}
}
 
 
/* The 'disable trace' command enables tracepoints.  Not supported by all targets.  */
/* The 'disable trace' command enables tracepoints.  Not supported by all targets.  */
static void
static void
disable_trace_command (args, from_tty)
disable_trace_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  dont_repeat ();
  dont_repeat ();
  map_args_over_tracepoints (args, from_tty, disable_op);
  map_args_over_tracepoints (args, from_tty, disable_op);
}
}
 
 
/* Remove a tracepoint (or all if no argument) */
/* Remove a tracepoint (or all if no argument) */
static void
static void
delete_trace_command (args, from_tty)
delete_trace_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  dont_repeat ();
  dont_repeat ();
  if (!args || !*args)          /* No args implies all tracepoints; */
  if (!args || !*args)          /* No args implies all tracepoints; */
    if (from_tty)               /* confirm only if from_tty... */
    if (from_tty)               /* confirm only if from_tty... */
      if (tracepoint_chain)     /* and if there are tracepoints to delete! */
      if (tracepoint_chain)     /* and if there are tracepoints to delete! */
        if (!query ("Delete all tracepoints? "))
        if (!query ("Delete all tracepoints? "))
          return;
          return;
 
 
  map_args_over_tracepoints (args, from_tty, delete_op);
  map_args_over_tracepoints (args, from_tty, delete_op);
}
}
 
 
/* Set passcount for tracepoint.
/* Set passcount for tracepoint.
 
 
   First command argument is passcount, second is tracepoint number.
   First command argument is passcount, second is tracepoint number.
   If tracepoint number omitted, apply to most recently defined.
   If tracepoint number omitted, apply to most recently defined.
   Also accepts special argument "all".  */
   Also accepts special argument "all".  */
 
 
static void
static void
trace_pass_command (args, from_tty)
trace_pass_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
  struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
  unsigned int count;
  unsigned int count;
  int all = 0;
  int all = 0;
 
 
  if (args == 0 || *args == 0)
  if (args == 0 || *args == 0)
    error ("passcount command requires an argument (count + optional TP num)");
    error ("passcount command requires an argument (count + optional TP num)");
 
 
  count = strtoul (args, &args, 10);    /* count comes first, then TP num */
  count = strtoul (args, &args, 10);    /* count comes first, then TP num */
 
 
  while (*args && isspace ((int) *args))
  while (*args && isspace ((int) *args))
    args++;
    args++;
 
 
  if (*args && strncasecmp (args, "all", 3) == 0)
  if (*args && strncasecmp (args, "all", 3) == 0)
    {
    {
      args += 3;                        /* skip special argument "all" */
      args += 3;                        /* skip special argument "all" */
      all = 1;
      all = 1;
      if (*args)
      if (*args)
        error ("Junk at end of arguments.");
        error ("Junk at end of arguments.");
    }
    }
  else
  else
    t1 = get_tracepoint_by_number (&args, 1, 1);
    t1 = get_tracepoint_by_number (&args, 1, 1);
 
 
  do
  do
    {
    {
      if (t1)
      if (t1)
        {
        {
          ALL_TRACEPOINTS (t2)
          ALL_TRACEPOINTS (t2)
            if (t1 == (struct tracepoint *) -1 || t1 == t2)
            if (t1 == (struct tracepoint *) -1 || t1 == t2)
              {
              {
                t2->pass_count = count;
                t2->pass_count = count;
                if (modify_tracepoint_hook)
                if (modify_tracepoint_hook)
                  modify_tracepoint_hook (t2);
                  modify_tracepoint_hook (t2);
                if (from_tty)
                if (from_tty)
                  printf_filtered ("Setting tracepoint %d's passcount to %d\n",
                  printf_filtered ("Setting tracepoint %d's passcount to %d\n",
                                   t2->number, count);
                                   t2->number, count);
              }
              }
          if (! all && *args)
          if (! all && *args)
            t1 = get_tracepoint_by_number (&args, 1, 0);
            t1 = get_tracepoint_by_number (&args, 1, 0);
        }
        }
    }
    }
  while (*args);
  while (*args);
}
}
 
 
/* ACTIONS functions: */
/* ACTIONS functions: */
 
 
/* Prototypes for action-parsing utility commands  */
/* Prototypes for action-parsing utility commands  */
static void read_actions PARAMS ((struct tracepoint *));
static void read_actions PARAMS ((struct tracepoint *));
 
 
/* The three functions:
/* The three functions:
   collect_pseudocommand,
   collect_pseudocommand,
   while_stepping_pseudocommand, and
   while_stepping_pseudocommand, and
   end_actions_pseudocommand
   end_actions_pseudocommand
   are placeholders for "commands" that are actually ONLY to be used
   are placeholders for "commands" that are actually ONLY to be used
   within a tracepoint action list.  If the actual function is ever called,
   within a tracepoint action list.  If the actual function is ever called,
   it means that somebody issued the "command" at the top level,
   it means that somebody issued the "command" at the top level,
   which is always an error.  */
   which is always an error.  */
 
 
static void
static void
end_actions_pseudocommand (args, from_tty)
end_actions_pseudocommand (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  error ("This command cannot be used at the top level.");
  error ("This command cannot be used at the top level.");
}
}
 
 
static void
static void
while_stepping_pseudocommand (args, from_tty)
while_stepping_pseudocommand (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  error ("This command can only be used in a tracepoint actions list.");
  error ("This command can only be used in a tracepoint actions list.");
}
}
 
 
static void
static void
collect_pseudocommand (args, from_tty)
collect_pseudocommand (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  error ("This command can only be used in a tracepoint actions list.");
  error ("This command can only be used in a tracepoint actions list.");
}
}
 
 
/* Enter a list of actions for a tracepoint.  */
/* Enter a list of actions for a tracepoint.  */
static void
static void
trace_actions_command (args, from_tty)
trace_actions_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  struct tracepoint *t;
  struct tracepoint *t;
  char tmpbuf[128];
  char tmpbuf[128];
  char *end_msg = "End with a line saying just \"end\".";
  char *end_msg = "End with a line saying just \"end\".";
 
 
  t = get_tracepoint_by_number (&args, 0, 1);
  t = get_tracepoint_by_number (&args, 0, 1);
  if (t)
  if (t)
    {
    {
      sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
      sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
               t->number);
               t->number);
 
 
      if (from_tty)
      if (from_tty)
        {
        {
          if (readline_begin_hook)
          if (readline_begin_hook)
            (*readline_begin_hook) ("%s  %s\n", tmpbuf, end_msg);
            (*readline_begin_hook) ("%s  %s\n", tmpbuf, end_msg);
          else if (input_from_terminal_p ())
          else if (input_from_terminal_p ())
            printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
            printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
        }
        }
 
 
      free_actions (t);
      free_actions (t);
      t->step_count = 0; /* read_actions may set this */
      t->step_count = 0; /* read_actions may set this */
      read_actions (t);
      read_actions (t);
 
 
      if (readline_end_hook)
      if (readline_end_hook)
        (*readline_end_hook) ();
        (*readline_end_hook) ();
      /* tracepoints_changed () */
      /* tracepoints_changed () */
    }
    }
  /* else just return */
  /* else just return */
}
}
 
 
/* worker function */
/* worker function */
static void
static void
read_actions (t)
read_actions (t)
     struct tracepoint *t;
     struct tracepoint *t;
{
{
  char *line;
  char *line;
  char *prompt1 = "> ", *prompt2 = "  > ";
  char *prompt1 = "> ", *prompt2 = "  > ";
  char *prompt = prompt1;
  char *prompt = prompt1;
  enum actionline_type linetype;
  enum actionline_type linetype;
  extern FILE *instream;
  extern FILE *instream;
  struct action_line *next = NULL, *temp;
  struct action_line *next = NULL, *temp;
  struct cleanup *old_chain;
  struct cleanup *old_chain;
 
 
  /* Control-C quits instantly if typed while in this loop
  /* Control-C quits instantly if typed while in this loop
     since it should not wait until the user types a newline.  */
     since it should not wait until the user types a newline.  */
  immediate_quit++;
  immediate_quit++;
#ifdef STOP_SIGNAL
#ifdef STOP_SIGNAL
  if (job_control)
  if (job_control)
    {
    {
      if (event_loop_p)
      if (event_loop_p)
        signal (STOP_SIGNAL, handle_stop_sig);
        signal (STOP_SIGNAL, handle_stop_sig);
      else
      else
        signal (STOP_SIGNAL, stop_sig);
        signal (STOP_SIGNAL, stop_sig);
    }
    }
#endif
#endif
  old_chain = make_cleanup ((make_cleanup_func) free_actions, (void *) t);
  old_chain = make_cleanup ((make_cleanup_func) free_actions, (void *) t);
  while (1)
  while (1)
    {
    {
      /* Make sure that all output has been output.  Some machines may let
      /* Make sure that all output has been output.  Some machines may let
         you get away with leaving out some of the gdb_flush, but not all.  */
         you get away with leaving out some of the gdb_flush, but not all.  */
      wrap_here ("");
      wrap_here ("");
      gdb_flush (gdb_stdout);
      gdb_flush (gdb_stdout);
      gdb_flush (gdb_stderr);
      gdb_flush (gdb_stderr);
 
 
      if (readline_hook && instream == NULL)
      if (readline_hook && instream == NULL)
        line = (*readline_hook) (prompt);
        line = (*readline_hook) (prompt);
      else if (instream == stdin && ISATTY (instream))
      else if (instream == stdin && ISATTY (instream))
        {
        {
          line = readline (prompt);
          line = readline (prompt);
          if (line && *line)    /* add it to command history */
          if (line && *line)    /* add it to command history */
            add_history (line);
            add_history (line);
        }
        }
      else
      else
        line = gdb_readline (0);
        line = gdb_readline (0);
 
 
      linetype = validate_actionline (&line, t);
      linetype = validate_actionline (&line, t);
      if (linetype == BADLINE)
      if (linetype == BADLINE)
        continue;               /* already warned -- collect another line */
        continue;               /* already warned -- collect another line */
 
 
      temp = xmalloc (sizeof (struct action_line));
      temp = xmalloc (sizeof (struct action_line));
      temp->next = NULL;
      temp->next = NULL;
      temp->action = line;
      temp->action = line;
 
 
      if (next == NULL)         /* first action for this tracepoint? */
      if (next == NULL)         /* first action for this tracepoint? */
        t->actions = next = temp;
        t->actions = next = temp;
      else
      else
        {
        {
          next->next = temp;
          next->next = temp;
          next = temp;
          next = temp;
        }
        }
 
 
      if (linetype == STEPPING) /* begin "while-stepping" */
      if (linetype == STEPPING) /* begin "while-stepping" */
        {
        {
          if (prompt == prompt2)
          if (prompt == prompt2)
            {
            {
              warning ("Already processing 'while-stepping'");
              warning ("Already processing 'while-stepping'");
              continue;
              continue;
            }
            }
          else
          else
            prompt = prompt2;   /* change prompt for stepping actions */
            prompt = prompt2;   /* change prompt for stepping actions */
        }
        }
      else if (linetype == END)
      else if (linetype == END)
        {
        {
          if (prompt == prompt2)
          if (prompt == prompt2)
            {
            {
              prompt = prompt1; /* end of single-stepping actions */
              prompt = prompt1; /* end of single-stepping actions */
            }
            }
          else
          else
            {                   /* end of actions */
            {                   /* end of actions */
              if (t->actions->next == NULL)
              if (t->actions->next == NULL)
                {
                {
                  /* an "end" all by itself with no other actions means
                  /* an "end" all by itself with no other actions means
                     this tracepoint has no actions.  Discard empty list. */
                     this tracepoint has no actions.  Discard empty list. */
                  free_actions (t);
                  free_actions (t);
                }
                }
              break;
              break;
            }
            }
        }
        }
    }
    }
#ifdef STOP_SIGNAL
#ifdef STOP_SIGNAL
  if (job_control)
  if (job_control)
    signal (STOP_SIGNAL, SIG_DFL);
    signal (STOP_SIGNAL, SIG_DFL);
#endif
#endif
  immediate_quit = 0;
  immediate_quit = 0;
  discard_cleanups (old_chain);
  discard_cleanups (old_chain);
}
}
 
 
/* worker function */
/* worker function */
enum actionline_type
enum actionline_type
validate_actionline (line, t)
validate_actionline (line, t)
     char **line;
     char **line;
     struct tracepoint *t;
     struct tracepoint *t;
{
{
  struct cmd_list_element *c;
  struct cmd_list_element *c;
  struct expression *exp = NULL;
  struct expression *exp = NULL;
  struct cleanup *old_chain = NULL;
  struct cleanup *old_chain = NULL;
  char *p;
  char *p;
 
 
  for (p = *line; isspace ((int) *p);)
  for (p = *line; isspace ((int) *p);)
    p++;
    p++;
 
 
  /* symbol lookup etc. */
  /* symbol lookup etc. */
  if (*p == '\0')               /* empty line: just prompt for another line. */
  if (*p == '\0')               /* empty line: just prompt for another line. */
    return BADLINE;
    return BADLINE;
 
 
  if (*p == '#')                /* comment line */
  if (*p == '#')                /* comment line */
    return GENERIC;
    return GENERIC;
 
 
  c = lookup_cmd (&p, cmdlist, "", -1, 1);
  c = lookup_cmd (&p, cmdlist, "", -1, 1);
  if (c == 0)
  if (c == 0)
    {
    {
      warning ("'%s' is not an action that I know, or is ambiguous.", p);
      warning ("'%s' is not an action that I know, or is ambiguous.", p);
      return BADLINE;
      return BADLINE;
    }
    }
 
 
  if (c->function.cfunc == collect_pseudocommand)
  if (c->function.cfunc == collect_pseudocommand)
    {
    {
      struct agent_expr *aexpr;
      struct agent_expr *aexpr;
      struct agent_reqs areqs;
      struct agent_reqs areqs;
 
 
      do
      do
        {                       /* repeat over a comma-separated list */
        {                       /* repeat over a comma-separated list */
          QUIT;                 /* allow user to bail out with ^C */
          QUIT;                 /* allow user to bail out with ^C */
          while (isspace ((int) *p))
          while (isspace ((int) *p))
            p++;
            p++;
 
 
          if (*p == '$')        /* look for special pseudo-symbols */
          if (*p == '$')        /* look for special pseudo-symbols */
            {
            {
              if ((0 == strncasecmp ("reg", p + 1, 3)) ||
              if ((0 == strncasecmp ("reg", p + 1, 3)) ||
                  (0 == strncasecmp ("arg", p + 1, 3)) ||
                  (0 == strncasecmp ("arg", p + 1, 3)) ||
                  (0 == strncasecmp ("loc", p + 1, 3)))
                  (0 == strncasecmp ("loc", p + 1, 3)))
                {
                {
                  p = strchr (p, ',');
                  p = strchr (p, ',');
                  continue;
                  continue;
                }
                }
              /* else fall thru, treat p as an expression and parse it! */
              /* else fall thru, treat p as an expression and parse it! */
            }
            }
          exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
          exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
          old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
          old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
                                    &exp);
                                    &exp);
 
 
          if (exp->elts[0].opcode == OP_VAR_VALUE)
          if (exp->elts[0].opcode == OP_VAR_VALUE)
            {
            {
              if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
              if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
                {
                {
                  warning ("constant %s (value %ld) will not be collected.",
                  warning ("constant %s (value %ld) will not be collected.",
                           SYMBOL_NAME (exp->elts[2].symbol),
                           SYMBOL_NAME (exp->elts[2].symbol),
                           SYMBOL_VALUE (exp->elts[2].symbol));
                           SYMBOL_VALUE (exp->elts[2].symbol));
                  return BADLINE;
                  return BADLINE;
                }
                }
              else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
              else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
                {
                {
                  warning ("%s is optimized away and cannot be collected.",
                  warning ("%s is optimized away and cannot be collected.",
                           SYMBOL_NAME (exp->elts[2].symbol));
                           SYMBOL_NAME (exp->elts[2].symbol));
                  return BADLINE;
                  return BADLINE;
                }
                }
            }
            }
 
 
          /* we have something to collect, make sure that the expr to
          /* we have something to collect, make sure that the expr to
             bytecode translator can handle it and that it's not too long */
             bytecode translator can handle it and that it's not too long */
          aexpr = gen_trace_for_expr (t->address, exp);
          aexpr = gen_trace_for_expr (t->address, exp);
          (void) make_cleanup ((make_cleanup_func) free_agent_expr, aexpr);
          (void) make_cleanup ((make_cleanup_func) free_agent_expr, aexpr);
 
 
          if (aexpr->len > MAX_AGENT_EXPR_LEN)
          if (aexpr->len > MAX_AGENT_EXPR_LEN)
            error ("expression too complicated, try simplifying");
            error ("expression too complicated, try simplifying");
 
 
          ax_reqs (aexpr, &areqs);
          ax_reqs (aexpr, &areqs);
          (void) make_cleanup (free, areqs.reg_mask);
          (void) make_cleanup (free, areqs.reg_mask);
 
 
          if (areqs.flaw != agent_flaw_none)
          if (areqs.flaw != agent_flaw_none)
            error ("malformed expression");
            error ("malformed expression");
 
 
          if (areqs.min_height < 0)
          if (areqs.min_height < 0)
            error ("gdb: Internal error: expression has min height < 0");
            error ("gdb: Internal error: expression has min height < 0");
 
 
          if (areqs.max_height > 20)
          if (areqs.max_height > 20)
            error ("expression too complicated, try simplifying");
            error ("expression too complicated, try simplifying");
 
 
          do_cleanups (old_chain);
          do_cleanups (old_chain);
        }
        }
      while (p && *p++ == ',');
      while (p && *p++ == ',');
      return GENERIC;
      return GENERIC;
    }
    }
  else if (c->function.cfunc == while_stepping_pseudocommand)
  else if (c->function.cfunc == while_stepping_pseudocommand)
    {
    {
      char *steparg;            /* in case warning is necessary */
      char *steparg;            /* in case warning is necessary */
 
 
      while (isspace ((int) *p))
      while (isspace ((int) *p))
        p++;
        p++;
      steparg = p;
      steparg = p;
 
 
      if (*p == '\0' ||
      if (*p == '\0' ||
          (t->step_count = strtol (p, &p, 0)) == 0)
          (t->step_count = strtol (p, &p, 0)) == 0)
        {
        {
          warning ("'%s': bad step-count; command ignored.", *line);
          warning ("'%s': bad step-count; command ignored.", *line);
          return BADLINE;
          return BADLINE;
        }
        }
      return STEPPING;
      return STEPPING;
    }
    }
  else if (c->function.cfunc == end_actions_pseudocommand)
  else if (c->function.cfunc == end_actions_pseudocommand)
    return END;
    return END;
  else
  else
    {
    {
      warning ("'%s' is not a supported tracepoint action.", *line);
      warning ("'%s' is not a supported tracepoint action.", *line);
      return BADLINE;
      return BADLINE;
    }
    }
}
}
 
 
/* worker function */
/* worker function */
void
void
free_actions (t)
free_actions (t)
     struct tracepoint *t;
     struct tracepoint *t;
{
{
  struct action_line *line, *next;
  struct action_line *line, *next;
 
 
  for (line = t->actions; line; line = next)
  for (line = t->actions; line; line = next)
    {
    {
      next = line->next;
      next = line->next;
      if (line->action)
      if (line->action)
        free (line->action);
        free (line->action);
      free (line);
      free (line);
    }
    }
  t->actions = NULL;
  t->actions = NULL;
}
}
 
 
struct memrange
struct memrange
{
{
  int type;             /* 0 for absolute memory range, else basereg number */
  int type;             /* 0 for absolute memory range, else basereg number */
  bfd_signed_vma start;
  bfd_signed_vma start;
  bfd_signed_vma end;
  bfd_signed_vma end;
};
};
 
 
struct collection_list
struct collection_list
  {
  {
    unsigned char regs_mask[8]; /* room for up to 256 regs */
    unsigned char regs_mask[8]; /* room for up to 256 regs */
    long listsize;
    long listsize;
    long next_memrange;
    long next_memrange;
    struct memrange *list;
    struct memrange *list;
    long aexpr_listsize;        /* size of array pointed to by expr_list elt */
    long aexpr_listsize;        /* size of array pointed to by expr_list elt */
    long next_aexpr_elt;
    long next_aexpr_elt;
    struct agent_expr **aexpr_list;
    struct agent_expr **aexpr_list;
 
 
  }
  }
tracepoint_list, stepping_list;
tracepoint_list, stepping_list;
 
 
/* MEMRANGE functions: */
/* MEMRANGE functions: */
 
 
static int memrange_cmp PARAMS ((const void *, const void *));
static int memrange_cmp PARAMS ((const void *, const void *));
 
 
/* compare memranges for qsort */
/* compare memranges for qsort */
static int
static int
memrange_cmp (va, vb)
memrange_cmp (va, vb)
     const void *va;
     const void *va;
     const void *vb;
     const void *vb;
{
{
  const struct memrange *a = va, *b = vb;
  const struct memrange *a = va, *b = vb;
 
 
  if (a->type < b->type)
  if (a->type < b->type)
    return -1;
    return -1;
  if (a->type > b->type)
  if (a->type > b->type)
    return 1;
    return 1;
  if (a->type == 0)
  if (a->type == 0)
    {
    {
      if ((bfd_vma) a->start < (bfd_vma) b->start)
      if ((bfd_vma) a->start < (bfd_vma) b->start)
        return -1;
        return -1;
      if ((bfd_vma) a->start > (bfd_vma) b->start)
      if ((bfd_vma) a->start > (bfd_vma) b->start)
        return 1;
        return 1;
    }
    }
  else
  else
    {
    {
      if (a->start < b->start)
      if (a->start < b->start)
        return -1;
        return -1;
      if (a->start > b->start)
      if (a->start > b->start)
        return 1;
        return 1;
    }
    }
  return 0;
  return 0;
}
}
 
 
/* Sort the memrange list using qsort, and merge adjacent memranges */
/* Sort the memrange list using qsort, and merge adjacent memranges */
static void
static void
memrange_sortmerge (memranges)
memrange_sortmerge (memranges)
     struct collection_list *memranges;
     struct collection_list *memranges;
{
{
  int a, b;
  int a, b;
 
 
  qsort (memranges->list, memranges->next_memrange,
  qsort (memranges->list, memranges->next_memrange,
         sizeof (struct memrange), memrange_cmp);
         sizeof (struct memrange), memrange_cmp);
  if (memranges->next_memrange > 0)
  if (memranges->next_memrange > 0)
    {
    {
      for (a = 0, b = 1; b < memranges->next_memrange; b++)
      for (a = 0, b = 1; b < memranges->next_memrange; b++)
        {
        {
          if (memranges->list[a].type == memranges->list[b].type &&
          if (memranges->list[a].type == memranges->list[b].type &&
              memranges->list[b].start - memranges->list[a].end <=
              memranges->list[b].start - memranges->list[a].end <=
              MAX_REGISTER_VIRTUAL_SIZE)
              MAX_REGISTER_VIRTUAL_SIZE)
            {
            {
              /* memrange b starts before memrange a ends; merge them.  */
              /* memrange b starts before memrange a ends; merge them.  */
              if (memranges->list[b].end > memranges->list[a].end)
              if (memranges->list[b].end > memranges->list[a].end)
                memranges->list[a].end = memranges->list[b].end;
                memranges->list[a].end = memranges->list[b].end;
              continue;         /* next b, same a */
              continue;         /* next b, same a */
            }
            }
          a++;                  /* next a */
          a++;                  /* next a */
          if (a != b)
          if (a != b)
            memcpy (&memranges->list[a], &memranges->list[b],
            memcpy (&memranges->list[a], &memranges->list[b],
                    sizeof (struct memrange));
                    sizeof (struct memrange));
        }
        }
      memranges->next_memrange = a + 1;
      memranges->next_memrange = a + 1;
    }
    }
}
}
 
 
/* Add a register to a collection list */
/* Add a register to a collection list */
static void
static void
add_register (collection, regno)
add_register (collection, regno)
     struct collection_list *collection;
     struct collection_list *collection;
     unsigned int regno;
     unsigned int regno;
{
{
  if (info_verbose)
  if (info_verbose)
    printf_filtered ("collect register %d\n", regno);
    printf_filtered ("collect register %d\n", regno);
  if (regno > (8 * sizeof (collection->regs_mask)))
  if (regno > (8 * sizeof (collection->regs_mask)))
    error ("Internal: register number %d too large for tracepoint",
    error ("Internal: register number %d too large for tracepoint",
           regno);
           regno);
  collection->regs_mask[regno / 8] |= 1 << (regno % 8);
  collection->regs_mask[regno / 8] |= 1 << (regno % 8);
}
}
 
 
/* Add a memrange to a collection list */
/* Add a memrange to a collection list */
static void
static void
add_memrange (memranges, type, base, len)
add_memrange (memranges, type, base, len)
     struct collection_list *memranges;
     struct collection_list *memranges;
     int type;
     int type;
     bfd_signed_vma base;
     bfd_signed_vma base;
     unsigned long len;
     unsigned long len;
{
{
  if (info_verbose)
  if (info_verbose)
    {
    {
      printf_filtered ("(%d,", type);
      printf_filtered ("(%d,", type);
      printf_vma (base);
      printf_vma (base);
      printf_filtered (",%ld)\n", len);
      printf_filtered (",%ld)\n", len);
    }
    }
 
 
  /* type: 0 == memory, n == basereg */
  /* type: 0 == memory, n == basereg */
  memranges->list[memranges->next_memrange].type = type;
  memranges->list[memranges->next_memrange].type = type;
  /* base: addr if memory, offset if reg relative. */
  /* base: addr if memory, offset if reg relative. */
  memranges->list[memranges->next_memrange].start = base;
  memranges->list[memranges->next_memrange].start = base;
  /* len: we actually save end (base + len) for convenience */
  /* len: we actually save end (base + len) for convenience */
  memranges->list[memranges->next_memrange].end = base + len;
  memranges->list[memranges->next_memrange].end = base + len;
  memranges->next_memrange++;
  memranges->next_memrange++;
  if (memranges->next_memrange >= memranges->listsize)
  if (memranges->next_memrange >= memranges->listsize)
    {
    {
      memranges->listsize *= 2;
      memranges->listsize *= 2;
      memranges->list = xrealloc (memranges->list,
      memranges->list = xrealloc (memranges->list,
                                  memranges->listsize);
                                  memranges->listsize);
    }
    }
 
 
  if (type != -1)               /* better collect the base register! */
  if (type != -1)               /* better collect the base register! */
    add_register (memranges, type);
    add_register (memranges, type);
}
}
 
 
/* Add a symbol to a collection list */
/* Add a symbol to a collection list */
static void
static void
collect_symbol (collect, sym, frame_regno, frame_offset)
collect_symbol (collect, sym, frame_regno, frame_offset)
     struct collection_list *collect;
     struct collection_list *collect;
     struct symbol *sym;
     struct symbol *sym;
     long frame_regno;
     long frame_regno;
     long frame_offset;
     long frame_offset;
{
{
  unsigned long len;
  unsigned long len;
  unsigned int reg;
  unsigned int reg;
  bfd_signed_vma offset;
  bfd_signed_vma offset;
 
 
  len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
  len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
  switch (SYMBOL_CLASS (sym))
  switch (SYMBOL_CLASS (sym))
    {
    {
    default:
    default:
      printf_filtered ("%s: don't know symbol class %d\n",
      printf_filtered ("%s: don't know symbol class %d\n",
                       SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
                       SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
      break;
      break;
    case LOC_CONST:
    case LOC_CONST:
      printf_filtered ("constant %s (value %ld) will not be collected.\n",
      printf_filtered ("constant %s (value %ld) will not be collected.\n",
                       SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
                       SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
      break;
      break;
    case LOC_STATIC:
    case LOC_STATIC:
      offset = SYMBOL_VALUE_ADDRESS (sym);
      offset = SYMBOL_VALUE_ADDRESS (sym);
      if (info_verbose)
      if (info_verbose)
        {
        {
          char tmp[40];
          char tmp[40];
 
 
          sprintf_vma (tmp, offset);
          sprintf_vma (tmp, offset);
          printf_filtered ("LOC_STATIC %s: collect %ld bytes at %s.\n",
          printf_filtered ("LOC_STATIC %s: collect %ld bytes at %s.\n",
                           SYMBOL_NAME (sym), len, tmp /* address */);
                           SYMBOL_NAME (sym), len, tmp /* address */);
        }
        }
      add_memrange (collect, -1, offset, len);  /* 0 == memory */
      add_memrange (collect, -1, offset, len);  /* 0 == memory */
      break;
      break;
    case LOC_REGISTER:
    case LOC_REGISTER:
    case LOC_REGPARM:
    case LOC_REGPARM:
      reg = SYMBOL_VALUE (sym);
      reg = SYMBOL_VALUE (sym);
      if (info_verbose)
      if (info_verbose)
        printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
        printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
      add_register (collect, reg);
      add_register (collect, reg);
      /* check for doubles stored in two registers */
      /* check for doubles stored in two registers */
      /* FIXME: how about larger types stored in 3 or more regs? */
      /* FIXME: how about larger types stored in 3 or more regs? */
      if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
      if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
          len > REGISTER_RAW_SIZE (reg))
          len > REGISTER_RAW_SIZE (reg))
        add_register (collect, reg + 1);
        add_register (collect, reg + 1);
      break;
      break;
    case LOC_REF_ARG:
    case LOC_REF_ARG:
      printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
      printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
      printf_filtered ("       (will not collect %s)\n",
      printf_filtered ("       (will not collect %s)\n",
                       SYMBOL_NAME (sym));
                       SYMBOL_NAME (sym));
      break;
      break;
    case LOC_ARG:
    case LOC_ARG:
      reg = frame_regno;
      reg = frame_regno;
      offset = frame_offset + SYMBOL_VALUE (sym);
      offset = frame_offset + SYMBOL_VALUE (sym);
      if (info_verbose)
      if (info_verbose)
        {
        {
          printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ",
          printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ",
                           SYMBOL_NAME (sym), len);
                           SYMBOL_NAME (sym), len);
          printf_vma (offset);
          printf_vma (offset);
          printf_filtered (" from frame ptr reg %d\n", reg);
          printf_filtered (" from frame ptr reg %d\n", reg);
        }
        }
      add_memrange (collect, reg, offset, len);
      add_memrange (collect, reg, offset, len);
      break;
      break;
    case LOC_REGPARM_ADDR:
    case LOC_REGPARM_ADDR:
      reg = SYMBOL_VALUE (sym);
      reg = SYMBOL_VALUE (sym);
      offset = 0;
      offset = 0;
      if (info_verbose)
      if (info_verbose)
        {
        {
          printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset ",
          printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset ",
                           SYMBOL_NAME (sym), len);
                           SYMBOL_NAME (sym), len);
          printf_vma (offset);
          printf_vma (offset);
          printf_filtered (" from reg %d\n", reg);
          printf_filtered (" from reg %d\n", reg);
        }
        }
      add_memrange (collect, reg, offset, len);
      add_memrange (collect, reg, offset, len);
      break;
      break;
    case LOC_LOCAL:
    case LOC_LOCAL:
    case LOC_LOCAL_ARG:
    case LOC_LOCAL_ARG:
      reg = frame_regno;
      reg = frame_regno;
      offset = frame_offset + SYMBOL_VALUE (sym);
      offset = frame_offset + SYMBOL_VALUE (sym);
      if (info_verbose)
      if (info_verbose)
        {
        {
          printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ",
          printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ",
                           SYMBOL_NAME (sym), len);
                           SYMBOL_NAME (sym), len);
          printf_vma (offset);
          printf_vma (offset);
          printf_filtered (" from frame ptr reg %d\n", reg);
          printf_filtered (" from frame ptr reg %d\n", reg);
        }
        }
      add_memrange (collect, reg, offset, len);
      add_memrange (collect, reg, offset, len);
      break;
      break;
    case LOC_BASEREG:
    case LOC_BASEREG:
    case LOC_BASEREG_ARG:
    case LOC_BASEREG_ARG:
      reg = SYMBOL_BASEREG (sym);
      reg = SYMBOL_BASEREG (sym);
      offset = SYMBOL_VALUE (sym);
      offset = SYMBOL_VALUE (sym);
      if (info_verbose)
      if (info_verbose)
        {
        {
          printf_filtered ("LOC_BASEREG %s: collect %ld bytes at offset ",
          printf_filtered ("LOC_BASEREG %s: collect %ld bytes at offset ",
                           SYMBOL_NAME (sym), len);
                           SYMBOL_NAME (sym), len);
          printf_vma (offset);
          printf_vma (offset);
          printf_filtered (" from basereg %d\n", reg);
          printf_filtered (" from basereg %d\n", reg);
        }
        }
      add_memrange (collect, reg, offset, len);
      add_memrange (collect, reg, offset, len);
      break;
      break;
    case LOC_UNRESOLVED:
    case LOC_UNRESOLVED:
      printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
      printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
      break;
      break;
    case LOC_OPTIMIZED_OUT:
    case LOC_OPTIMIZED_OUT:
      printf_filtered ("%s has been optimized out of existance.\n",
      printf_filtered ("%s has been optimized out of existance.\n",
                       SYMBOL_NAME (sym));
                       SYMBOL_NAME (sym));
      break;
      break;
    }
    }
}
}
 
 
/* Add all locals (or args) symbols to collection list */
/* Add all locals (or args) symbols to collection list */
static void
static void
add_local_symbols (collect, pc, frame_regno, frame_offset, type)
add_local_symbols (collect, pc, frame_regno, frame_offset, type)
     struct collection_list *collect;
     struct collection_list *collect;
     CORE_ADDR pc;
     CORE_ADDR pc;
     long frame_regno;
     long frame_regno;
     long frame_offset;
     long frame_offset;
     int type;
     int type;
{
{
  struct symbol *sym;
  struct symbol *sym;
  struct block *block;
  struct block *block;
  int i, nsyms, count = 0;
  int i, nsyms, count = 0;
 
 
  block = block_for_pc (pc);
  block = block_for_pc (pc);
  while (block != 0)
  while (block != 0)
    {
    {
      QUIT;                     /* allow user to bail out with ^C */
      QUIT;                     /* allow user to bail out with ^C */
      nsyms = BLOCK_NSYMS (block);
      nsyms = BLOCK_NSYMS (block);
      for (i = 0; i < nsyms; i++)
      for (i = 0; i < nsyms; i++)
        {
        {
          sym = BLOCK_SYM (block, i);
          sym = BLOCK_SYM (block, i);
          switch (SYMBOL_CLASS (sym))
          switch (SYMBOL_CLASS (sym))
            {
            {
            default:
            default:
              warning ("don't know how to trace local symbol %s",
              warning ("don't know how to trace local symbol %s",
                       SYMBOL_NAME (sym));
                       SYMBOL_NAME (sym));
            case LOC_LOCAL:
            case LOC_LOCAL:
            case LOC_STATIC:
            case LOC_STATIC:
            case LOC_REGISTER:
            case LOC_REGISTER:
            case LOC_BASEREG:
            case LOC_BASEREG:
              if (type == 'L')  /* collecting Locals */
              if (type == 'L')  /* collecting Locals */
                {
                {
                  count++;
                  count++;
                  collect_symbol (collect, sym, frame_regno, frame_offset);
                  collect_symbol (collect, sym, frame_regno, frame_offset);
                }
                }
              break;
              break;
            case LOC_ARG:
            case LOC_ARG:
            case LOC_LOCAL_ARG:
            case LOC_LOCAL_ARG:
            case LOC_REF_ARG:
            case LOC_REF_ARG:
            case LOC_REGPARM:
            case LOC_REGPARM:
            case LOC_REGPARM_ADDR:
            case LOC_REGPARM_ADDR:
            case LOC_BASEREG_ARG:
            case LOC_BASEREG_ARG:
              if (type == 'A')  /* collecting Arguments */
              if (type == 'A')  /* collecting Arguments */
                {
                {
                  count++;
                  count++;
                  collect_symbol (collect, sym, frame_regno, frame_offset);
                  collect_symbol (collect, sym, frame_regno, frame_offset);
                }
                }
            }
            }
        }
        }
      if (BLOCK_FUNCTION (block))
      if (BLOCK_FUNCTION (block))
        break;
        break;
      else
      else
        block = BLOCK_SUPERBLOCK (block);
        block = BLOCK_SUPERBLOCK (block);
    }
    }
  if (count == 0)
  if (count == 0)
    warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
    warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
}
}
 
 
/* worker function */
/* worker function */
static void
static void
clear_collection_list (list)
clear_collection_list (list)
     struct collection_list *list;
     struct collection_list *list;
{
{
  int ndx;
  int ndx;
 
 
  list->next_memrange = 0;
  list->next_memrange = 0;
  for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
  for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
    {
    {
      free_agent_expr (list->aexpr_list[ndx]);
      free_agent_expr (list->aexpr_list[ndx]);
      list->aexpr_list[ndx] = NULL;
      list->aexpr_list[ndx] = NULL;
    }
    }
  list->next_aexpr_elt = 0;
  list->next_aexpr_elt = 0;
  memset (list->regs_mask, 0, sizeof (list->regs_mask));
  memset (list->regs_mask, 0, sizeof (list->regs_mask));
}
}
 
 
/* reduce a collection list to string form (for gdb protocol) */
/* reduce a collection list to string form (for gdb protocol) */
static char **
static char **
stringify_collection_list (list, string)
stringify_collection_list (list, string)
     struct collection_list *list;
     struct collection_list *list;
     char *string;
     char *string;
{
{
  char temp_buf[2048];
  char temp_buf[2048];
  char tmp2[40];
  char tmp2[40];
  int count;
  int count;
  int ndx = 0;
  int ndx = 0;
  char *(*str_list)[];
  char *(*str_list)[];
  char *end;
  char *end;
  long i;
  long i;
 
 
  count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
  count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
  str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
  str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
 
 
  for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
  for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
    if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
    if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
      break;
      break;
  if (list->regs_mask[i] != 0)   /* prepare to send regs_mask to the stub */
  if (list->regs_mask[i] != 0)   /* prepare to send regs_mask to the stub */
    {
    {
      if (info_verbose)
      if (info_verbose)
        printf_filtered ("\nCollecting registers (mask): 0x");
        printf_filtered ("\nCollecting registers (mask): 0x");
      end = temp_buf;
      end = temp_buf;
      *end++ = 'R';
      *end++ = 'R';
      for (; i >= 0; i--)
      for (; i >= 0; i--)
        {
        {
          QUIT;                 /* allow user to bail out with ^C */
          QUIT;                 /* allow user to bail out with ^C */
          if (info_verbose)
          if (info_verbose)
            printf_filtered ("%02X", list->regs_mask[i]);
            printf_filtered ("%02X", list->regs_mask[i]);
          sprintf (end, "%02X", list->regs_mask[i]);
          sprintf (end, "%02X", list->regs_mask[i]);
          end += 2;
          end += 2;
        }
        }
      (*str_list)[ndx] = savestring (temp_buf, end - temp_buf);
      (*str_list)[ndx] = savestring (temp_buf, end - temp_buf);
      ndx++;
      ndx++;
    }
    }
  if (info_verbose)
  if (info_verbose)
    printf_filtered ("\n");
    printf_filtered ("\n");
  if (list->next_memrange > 0 && info_verbose)
  if (list->next_memrange > 0 && info_verbose)
    printf_filtered ("Collecting memranges: \n");
    printf_filtered ("Collecting memranges: \n");
  for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
  for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
    {
    {
      QUIT;                     /* allow user to bail out with ^C */
      QUIT;                     /* allow user to bail out with ^C */
      sprintf_vma (tmp2, list->list[i].start);
      sprintf_vma (tmp2, list->list[i].start);
      if (info_verbose)
      if (info_verbose)
        {
        {
          printf_filtered ("(%d, %s, %ld)\n",
          printf_filtered ("(%d, %s, %ld)\n",
                           list->list[i].type,
                           list->list[i].type,
                           tmp2,
                           tmp2,
                           (long) (list->list[i].end - list->list[i].start));
                           (long) (list->list[i].end - list->list[i].start));
        }
        }
      if (count + 27 > MAX_AGENT_EXPR_LEN)
      if (count + 27 > MAX_AGENT_EXPR_LEN)
        {
        {
          (*str_list)[ndx] = savestring (temp_buf, count);
          (*str_list)[ndx] = savestring (temp_buf, count);
          ndx++;
          ndx++;
          count = 0;
          count = 0;
          end = temp_buf;
          end = temp_buf;
        }
        }
 
 
      sprintf (end, "M%X,%s,%lX",
      sprintf (end, "M%X,%s,%lX",
               list->list[i].type,
               list->list[i].type,
               tmp2,
               tmp2,
               (long) (list->list[i].end - list->list[i].start));
               (long) (list->list[i].end - list->list[i].start));
 
 
      count += strlen (end);
      count += strlen (end);
      end += count;
      end += count;
    }
    }
 
 
  for (i = 0; i < list->next_aexpr_elt; i++)
  for (i = 0; i < list->next_aexpr_elt; i++)
    {
    {
      QUIT;                     /* allow user to bail out with ^C */
      QUIT;                     /* allow user to bail out with ^C */
      if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
      if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
        {
        {
          (*str_list)[ndx] = savestring (temp_buf, count);
          (*str_list)[ndx] = savestring (temp_buf, count);
          ndx++;
          ndx++;
          count = 0;
          count = 0;
          end = temp_buf;
          end = temp_buf;
        }
        }
      sprintf (end, "X%08X,", list->aexpr_list[i]->len);
      sprintf (end, "X%08X,", list->aexpr_list[i]->len);
      end += 10;                /* 'X' + 8 hex digits + ',' */
      end += 10;                /* 'X' + 8 hex digits + ',' */
      count += 10;
      count += 10;
 
 
      end = mem2hex (list->aexpr_list[i]->buf, end, list->aexpr_list[i]->len);
      end = mem2hex (list->aexpr_list[i]->buf, end, list->aexpr_list[i]->len);
      count += 2 * list->aexpr_list[i]->len;
      count += 2 * list->aexpr_list[i]->len;
    }
    }
 
 
  if (count != 0)
  if (count != 0)
    {
    {
      (*str_list)[ndx] = savestring (temp_buf, count);
      (*str_list)[ndx] = savestring (temp_buf, count);
      ndx++;
      ndx++;
      count = 0;
      count = 0;
      end = temp_buf;
      end = temp_buf;
    }
    }
  (*str_list)[ndx] = NULL;
  (*str_list)[ndx] = NULL;
 
 
  if (ndx == 0)
  if (ndx == 0)
    return NULL;
    return NULL;
  else
  else
    return *str_list;
    return *str_list;
}
}
 
 
static void
static void
free_actions_list_cleanup_wrapper (al)
free_actions_list_cleanup_wrapper (al)
     void *al;
     void *al;
{
{
  free_actions_list (al);
  free_actions_list (al);
}
}
 
 
static void
static void
free_actions_list (actions_list)
free_actions_list (actions_list)
     char **actions_list;
     char **actions_list;
{
{
  int ndx;
  int ndx;
 
 
  if (actions_list == 0)
  if (actions_list == 0)
    return;
    return;
 
 
  for (ndx = 0; actions_list[ndx]; ndx++)
  for (ndx = 0; actions_list[ndx]; ndx++)
    free (actions_list[ndx]);
    free (actions_list[ndx]);
 
 
  free (actions_list);
  free (actions_list);
}
}
 
 
/* render all actions into gdb protocol */
/* render all actions into gdb protocol */
static void
static void
encode_actions (t, tdp_actions, stepping_actions)
encode_actions (t, tdp_actions, stepping_actions)
     struct tracepoint *t;
     struct tracepoint *t;
     char ***tdp_actions;
     char ***tdp_actions;
     char ***stepping_actions;
     char ***stepping_actions;
{
{
  static char tdp_buff[2048], step_buff[2048];
  static char tdp_buff[2048], step_buff[2048];
  char *action_exp;
  char *action_exp;
  struct expression *exp = NULL;
  struct expression *exp = NULL;
  struct action_line *action;
  struct action_line *action;
  int i;
  int i;
  value_ptr tempval;
  value_ptr tempval;
  struct collection_list *collect;
  struct collection_list *collect;
  struct cmd_list_element *cmd;
  struct cmd_list_element *cmd;
  struct agent_expr *aexpr;
  struct agent_expr *aexpr;
  long frame_reg, frame_offset;
  long frame_reg, frame_offset;
 
 
 
 
  clear_collection_list (&tracepoint_list);
  clear_collection_list (&tracepoint_list);
  clear_collection_list (&stepping_list);
  clear_collection_list (&stepping_list);
  collect = &tracepoint_list;
  collect = &tracepoint_list;
 
 
  *tdp_actions = NULL;
  *tdp_actions = NULL;
  *stepping_actions = NULL;
  *stepping_actions = NULL;
 
 
  TARGET_VIRTUAL_FRAME_POINTER (t->address, &frame_reg, &frame_offset);
  TARGET_VIRTUAL_FRAME_POINTER (t->address, &frame_reg, &frame_offset);
 
 
  for (action = t->actions; action; action = action->next)
  for (action = t->actions; action; action = action->next)
    {
    {
      QUIT;                     /* allow user to bail out with ^C */
      QUIT;                     /* allow user to bail out with ^C */
      action_exp = action->action;
      action_exp = action->action;
      while (isspace ((int) *action_exp))
      while (isspace ((int) *action_exp))
        action_exp++;
        action_exp++;
 
 
      if (*action_exp == '#')   /* comment line */
      if (*action_exp == '#')   /* comment line */
        return;
        return;
 
 
      cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
      cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
      if (cmd == 0)
      if (cmd == 0)
        error ("Bad action list item: %s", action_exp);
        error ("Bad action list item: %s", action_exp);
 
 
      if (cmd->function.cfunc == collect_pseudocommand)
      if (cmd->function.cfunc == collect_pseudocommand)
        {
        {
          do
          do
            {                   /* repeat over a comma-separated list */
            {                   /* repeat over a comma-separated list */
              QUIT;             /* allow user to bail out with ^C */
              QUIT;             /* allow user to bail out with ^C */
              while (isspace ((int) *action_exp))
              while (isspace ((int) *action_exp))
                action_exp++;
                action_exp++;
 
 
              if (0 == strncasecmp ("$reg", action_exp, 4))
              if (0 == strncasecmp ("$reg", action_exp, 4))
                {
                {
                  for (i = 0; i < NUM_REGS; i++)
                  for (i = 0; i < NUM_REGS; i++)
                    add_register (collect, i);
                    add_register (collect, i);
                  action_exp = strchr (action_exp, ',');        /* more? */
                  action_exp = strchr (action_exp, ',');        /* more? */
                }
                }
              else if (0 == strncasecmp ("$arg", action_exp, 4))
              else if (0 == strncasecmp ("$arg", action_exp, 4))
                {
                {
                  add_local_symbols (collect,
                  add_local_symbols (collect,
                                     t->address,
                                     t->address,
                                     frame_reg,
                                     frame_reg,
                                     frame_offset,
                                     frame_offset,
                                     'A');
                                     'A');
                  action_exp = strchr (action_exp, ',');        /* more? */
                  action_exp = strchr (action_exp, ',');        /* more? */
                }
                }
              else if (0 == strncasecmp ("$loc", action_exp, 4))
              else if (0 == strncasecmp ("$loc", action_exp, 4))
                {
                {
                  add_local_symbols (collect,
                  add_local_symbols (collect,
                                     t->address,
                                     t->address,
                                     frame_reg,
                                     frame_reg,
                                     frame_offset,
                                     frame_offset,
                                     'L');
                                     'L');
                  action_exp = strchr (action_exp, ',');        /* more? */
                  action_exp = strchr (action_exp, ',');        /* more? */
                }
                }
              else
              else
                {
                {
                  unsigned long addr, len;
                  unsigned long addr, len;
                  struct cleanup *old_chain = NULL;
                  struct cleanup *old_chain = NULL;
                  struct cleanup *old_chain1 = NULL;
                  struct cleanup *old_chain1 = NULL;
                  struct agent_reqs areqs;
                  struct agent_reqs areqs;
 
 
                  exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
                  exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
                  old_chain = make_cleanup ((make_cleanup_func)
                  old_chain = make_cleanup ((make_cleanup_func)
                                            free_current_contents, &exp);
                                            free_current_contents, &exp);
 
 
                  switch (exp->elts[0].opcode)
                  switch (exp->elts[0].opcode)
                    {
                    {
                    case OP_REGISTER:
                    case OP_REGISTER:
                      i = exp->elts[1].longconst;
                      i = exp->elts[1].longconst;
                      if (info_verbose)
                      if (info_verbose)
                        printf_filtered ("OP_REGISTER: ");
                        printf_filtered ("OP_REGISTER: ");
                      add_register (collect, i);
                      add_register (collect, i);
                      break;
                      break;
 
 
                    case UNOP_MEMVAL:
                    case UNOP_MEMVAL:
                      /* safe because we know it's a simple expression */
                      /* safe because we know it's a simple expression */
                      tempval = evaluate_expression (exp);
                      tempval = evaluate_expression (exp);
                      addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
                      addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
                      len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
                      len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
                      add_memrange (collect, -1, addr, len);
                      add_memrange (collect, -1, addr, len);
                      break;
                      break;
 
 
                    case OP_VAR_VALUE:
                    case OP_VAR_VALUE:
                      collect_symbol (collect,
                      collect_symbol (collect,
                                      exp->elts[2].symbol,
                                      exp->elts[2].symbol,
                                      frame_reg,
                                      frame_reg,
                                      frame_offset);
                                      frame_offset);
                      break;
                      break;
 
 
                    default:    /* full-fledged expression */
                    default:    /* full-fledged expression */
                      aexpr = gen_trace_for_expr (t->address, exp);
                      aexpr = gen_trace_for_expr (t->address, exp);
 
 
                      old_chain1 = make_cleanup ((make_cleanup_func)
                      old_chain1 = make_cleanup ((make_cleanup_func)
                                                 free_agent_expr, aexpr);
                                                 free_agent_expr, aexpr);
 
 
                      ax_reqs (aexpr, &areqs);
                      ax_reqs (aexpr, &areqs);
                      if (areqs.flaw != agent_flaw_none)
                      if (areqs.flaw != agent_flaw_none)
                        error ("malformed expression");
                        error ("malformed expression");
 
 
                      if (areqs.min_height < 0)
                      if (areqs.min_height < 0)
                        error ("gdb: Internal error: expression has min height < 0");
                        error ("gdb: Internal error: expression has min height < 0");
                      if (areqs.max_height > 20)
                      if (areqs.max_height > 20)
                        error ("expression too complicated, try simplifying");
                        error ("expression too complicated, try simplifying");
 
 
                      discard_cleanups (old_chain1);
                      discard_cleanups (old_chain1);
                      add_aexpr (collect, aexpr);
                      add_aexpr (collect, aexpr);
 
 
                      /* take care of the registers */
                      /* take care of the registers */
                      if (areqs.reg_mask_len > 0)
                      if (areqs.reg_mask_len > 0)
                        {
                        {
                          int ndx1;
                          int ndx1;
                          int ndx2;
                          int ndx2;
 
 
                          for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
                          for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
                            {
                            {
                              QUIT;     /* allow user to bail out with ^C */
                              QUIT;     /* allow user to bail out with ^C */
                              if (areqs.reg_mask[ndx1] != 0)
                              if (areqs.reg_mask[ndx1] != 0)
                                {
                                {
                                  /* assume chars have 8 bits */
                                  /* assume chars have 8 bits */
                                  for (ndx2 = 0; ndx2 < 8; ndx2++)
                                  for (ndx2 = 0; ndx2 < 8; ndx2++)
                                    if (areqs.reg_mask[ndx1] & (1 << ndx2))
                                    if (areqs.reg_mask[ndx1] & (1 << ndx2))
                                      /* it's used -- record it */
                                      /* it's used -- record it */
                                      add_register (collect, ndx1 * 8 + ndx2);
                                      add_register (collect, ndx1 * 8 + ndx2);
                                }
                                }
                            }
                            }
                        }
                        }
                      break;
                      break;
                    }           /* switch */
                    }           /* switch */
                  do_cleanups (old_chain);
                  do_cleanups (old_chain);
                }               /* do */
                }               /* do */
            }
            }
          while (action_exp && *action_exp++ == ',');
          while (action_exp && *action_exp++ == ',');
        }                       /* if */
        }                       /* if */
      else if (cmd->function.cfunc == while_stepping_pseudocommand)
      else if (cmd->function.cfunc == while_stepping_pseudocommand)
        {
        {
          collect = &stepping_list;
          collect = &stepping_list;
        }
        }
      else if (cmd->function.cfunc == end_actions_pseudocommand)
      else if (cmd->function.cfunc == end_actions_pseudocommand)
        {
        {
          if (collect == &stepping_list)        /* end stepping actions */
          if (collect == &stepping_list)        /* end stepping actions */
            collect = &tracepoint_list;
            collect = &tracepoint_list;
          else
          else
            break;              /* end tracepoint actions */
            break;              /* end tracepoint actions */
        }
        }
    }                           /* for */
    }                           /* for */
  memrange_sortmerge (&tracepoint_list);
  memrange_sortmerge (&tracepoint_list);
  memrange_sortmerge (&stepping_list);
  memrange_sortmerge (&stepping_list);
 
 
  *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
  *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
  *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
  *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
}
}
 
 
static void
static void
add_aexpr (collect, aexpr)
add_aexpr (collect, aexpr)
     struct collection_list *collect;
     struct collection_list *collect;
     struct agent_expr *aexpr;
     struct agent_expr *aexpr;
{
{
  if (collect->next_aexpr_elt >= collect->aexpr_listsize)
  if (collect->next_aexpr_elt >= collect->aexpr_listsize)
    {
    {
      collect->aexpr_list =
      collect->aexpr_list =
        xrealloc (collect->aexpr_list,
        xrealloc (collect->aexpr_list,
                2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
                2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
      collect->aexpr_listsize *= 2;
      collect->aexpr_listsize *= 2;
    }
    }
  collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
  collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
  collect->next_aexpr_elt++;
  collect->next_aexpr_elt++;
}
}
 
 
static char target_buf[2048];
static char target_buf[2048];
 
 
/* Set "transparent" memory ranges
/* Set "transparent" memory ranges
 
 
   Allow trace mechanism to treat text-like sections
   Allow trace mechanism to treat text-like sections
   (and perhaps all read-only sections) transparently,
   (and perhaps all read-only sections) transparently,
   i.e. don't reject memory requests from these address ranges
   i.e. don't reject memory requests from these address ranges
   just because they haven't been collected.  */
   just because they haven't been collected.  */
 
 
static void
static void
remote_set_transparent_ranges (void)
remote_set_transparent_ranges (void)
{
{
  extern bfd *exec_bfd;
  extern bfd *exec_bfd;
  asection *s;
  asection *s;
  bfd_size_type size;
  bfd_size_type size;
  bfd_vma lma;
  bfd_vma lma;
  int anysecs = 0;
  int anysecs = 0;
 
 
  if (!exec_bfd)
  if (!exec_bfd)
    return;                     /* no information to give. */
    return;                     /* no information to give. */
 
 
  strcpy (target_buf, "QTro");
  strcpy (target_buf, "QTro");
  for (s = exec_bfd->sections; s; s = s->next)
  for (s = exec_bfd->sections; s; s = s->next)
    {
    {
      char tmp1[40], tmp2[40];
      char tmp1[40], tmp2[40];
 
 
      if ((s->flags & SEC_LOAD) == 0 ||
      if ((s->flags & SEC_LOAD) == 0 ||
      /* (s->flags & SEC_CODE)     == 0 || */
      /* (s->flags & SEC_CODE)     == 0 || */
          (s->flags & SEC_READONLY) == 0)
          (s->flags & SEC_READONLY) == 0)
        continue;
        continue;
 
 
      anysecs = 1;
      anysecs = 1;
      lma = s->lma;
      lma = s->lma;
      size = bfd_get_section_size_before_reloc (s);
      size = bfd_get_section_size_before_reloc (s);
      sprintf_vma (tmp1, lma);
      sprintf_vma (tmp1, lma);
      sprintf_vma (tmp2, lma + size);
      sprintf_vma (tmp2, lma + size);
      sprintf (target_buf + strlen (target_buf),
      sprintf (target_buf + strlen (target_buf),
               ":%s,%s", tmp1, tmp2);
               ":%s,%s", tmp1, tmp2);
    }
    }
  if (anysecs)
  if (anysecs)
    {
    {
      putpkt (target_buf);
      putpkt (target_buf);
      getpkt (target_buf, sizeof (target_buf), 0);
      getpkt (target_buf, sizeof (target_buf), 0);
    }
    }
}
}
 
 
/* tstart command:
/* tstart command:
 
 
   Tell target to clear any previous trace experiment.
   Tell target to clear any previous trace experiment.
   Walk the list of tracepoints, and send them (and their actions)
   Walk the list of tracepoints, and send them (and their actions)
   to the target.  If no errors,
   to the target.  If no errors,
   Tell target to start a new trace experiment.  */
   Tell target to start a new trace experiment.  */
 
 
static void
static void
trace_start_command (args, from_tty)
trace_start_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{                               /* STUB_COMM MOSTLY_IMPLEMENTED */
{                               /* STUB_COMM MOSTLY_IMPLEMENTED */
  struct tracepoint *t;
  struct tracepoint *t;
  char buf[2048];
  char buf[2048];
  char **tdp_actions;
  char **tdp_actions;
  char **stepping_actions;
  char **stepping_actions;
  int ndx;
  int ndx;
  struct cleanup *old_chain = NULL;
  struct cleanup *old_chain = NULL;
 
 
  dont_repeat ();               /* like "run", dangerous to repeat accidentally */
  dont_repeat ();               /* like "run", dangerous to repeat accidentally */
 
 
  if (target_is_remote ())
  if (target_is_remote ())
    {
    {
      putpkt ("QTinit");
      putpkt ("QTinit");
      remote_get_noisy_reply (target_buf, sizeof (target_buf));
      remote_get_noisy_reply (target_buf, sizeof (target_buf));
      if (strcmp (target_buf, "OK"))
      if (strcmp (target_buf, "OK"))
        error ("Target does not support this command.");
        error ("Target does not support this command.");
 
 
      ALL_TRACEPOINTS (t)
      ALL_TRACEPOINTS (t)
      {
      {
        char tmp[40];
        char tmp[40];
 
 
        sprintf_vma (tmp, t->address);
        sprintf_vma (tmp, t->address);
        sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number, tmp, /* address */
        sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number, tmp, /* address */
                 t->enabled == enabled ? 'E' : 'D',
                 t->enabled == enabled ? 'E' : 'D',
                 t->step_count, t->pass_count);
                 t->step_count, t->pass_count);
 
 
        if (t->actions)
        if (t->actions)
          strcat (buf, "-");
          strcat (buf, "-");
        putpkt (buf);
        putpkt (buf);
        remote_get_noisy_reply (target_buf, sizeof (target_buf));
        remote_get_noisy_reply (target_buf, sizeof (target_buf));
        if (strcmp (target_buf, "OK"))
        if (strcmp (target_buf, "OK"))
          error ("Target does not support tracepoints.");
          error ("Target does not support tracepoints.");
 
 
        if (t->actions)
        if (t->actions)
          {
          {
            encode_actions (t, &tdp_actions, &stepping_actions);
            encode_actions (t, &tdp_actions, &stepping_actions);
            old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
            old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
                                      tdp_actions);
                                      tdp_actions);
            (void) make_cleanup (free_actions_list_cleanup_wrapper,
            (void) make_cleanup (free_actions_list_cleanup_wrapper,
                                 stepping_actions);
                                 stepping_actions);
 
 
            /* do_single_steps (t); */
            /* do_single_steps (t); */
            if (tdp_actions)
            if (tdp_actions)
              {
              {
                for (ndx = 0; tdp_actions[ndx]; ndx++)
                for (ndx = 0; tdp_actions[ndx]; ndx++)
                  {
                  {
                    QUIT;       /* allow user to bail out with ^C */
                    QUIT;       /* allow user to bail out with ^C */
                    sprintf (buf, "QTDP:-%x:%s:%s%c",
                    sprintf (buf, "QTDP:-%x:%s:%s%c",
                             t->number, tmp, /* address */
                             t->number, tmp, /* address */
                             tdp_actions[ndx],
                             tdp_actions[ndx],
                             ((tdp_actions[ndx + 1] || stepping_actions)
                             ((tdp_actions[ndx + 1] || stepping_actions)
                              ? '-' : 0));
                              ? '-' : 0));
                    putpkt (buf);
                    putpkt (buf);
                    remote_get_noisy_reply (target_buf, sizeof (target_buf));
                    remote_get_noisy_reply (target_buf, sizeof (target_buf));
                    if (strcmp (target_buf, "OK"))
                    if (strcmp (target_buf, "OK"))
                      error ("Error on target while setting tracepoints.");
                      error ("Error on target while setting tracepoints.");
                  }
                  }
              }
              }
            if (stepping_actions)
            if (stepping_actions)
              {
              {
                for (ndx = 0; stepping_actions[ndx]; ndx++)
                for (ndx = 0; stepping_actions[ndx]; ndx++)
                  {
                  {
                    QUIT;       /* allow user to bail out with ^C */
                    QUIT;       /* allow user to bail out with ^C */
                    sprintf (buf, "QTDP:-%x:%s:%s%s%s",
                    sprintf (buf, "QTDP:-%x:%s:%s%s%s",
                             t->number, tmp, /* address */
                             t->number, tmp, /* address */
                             ((ndx == 0) ? "S" : ""),
                             ((ndx == 0) ? "S" : ""),
                             stepping_actions[ndx],
                             stepping_actions[ndx],
                             (stepping_actions[ndx + 1] ? "-" : ""));
                             (stepping_actions[ndx + 1] ? "-" : ""));
                    putpkt (buf);
                    putpkt (buf);
                    remote_get_noisy_reply (target_buf, sizeof (target_buf));
                    remote_get_noisy_reply (target_buf, sizeof (target_buf));
                    if (strcmp (target_buf, "OK"))
                    if (strcmp (target_buf, "OK"))
                      error ("Error on target while setting tracepoints.");
                      error ("Error on target while setting tracepoints.");
                  }
                  }
              }
              }
 
 
            do_cleanups (old_chain);
            do_cleanups (old_chain);
          }
          }
      }
      }
      /* Tell target to treat text-like sections as transparent */
      /* Tell target to treat text-like sections as transparent */
      remote_set_transparent_ranges ();
      remote_set_transparent_ranges ();
      /* Now insert traps and begin collecting data */
      /* Now insert traps and begin collecting data */
      putpkt ("QTStart");
      putpkt ("QTStart");
      remote_get_noisy_reply (target_buf, sizeof (target_buf));
      remote_get_noisy_reply (target_buf, sizeof (target_buf));
      if (strcmp (target_buf, "OK"))
      if (strcmp (target_buf, "OK"))
        error ("Bogus reply from target: %s", target_buf);
        error ("Bogus reply from target: %s", target_buf);
      set_traceframe_num (-1);  /* all old traceframes invalidated */
      set_traceframe_num (-1);  /* all old traceframes invalidated */
      set_tracepoint_num (-1);
      set_tracepoint_num (-1);
      set_traceframe_context (-1);
      set_traceframe_context (-1);
      trace_running_p = 1;
      trace_running_p = 1;
      if (trace_start_stop_hook)
      if (trace_start_stop_hook)
        trace_start_stop_hook (1, from_tty);
        trace_start_stop_hook (1, from_tty);
 
 
    }
    }
  else
  else
    error ("Trace can only be run on remote targets.");
    error ("Trace can only be run on remote targets.");
}
}
 
 
/* tstop command */
/* tstop command */
static void
static void
trace_stop_command (args, from_tty)
trace_stop_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{                               /* STUB_COMM IS_IMPLEMENTED */
{                               /* STUB_COMM IS_IMPLEMENTED */
  if (target_is_remote ())
  if (target_is_remote ())
    {
    {
      putpkt ("QTStop");
      putpkt ("QTStop");
      remote_get_noisy_reply (target_buf, sizeof (target_buf));
      remote_get_noisy_reply (target_buf, sizeof (target_buf));
      if (strcmp (target_buf, "OK"))
      if (strcmp (target_buf, "OK"))
        error ("Bogus reply from target: %s", target_buf);
        error ("Bogus reply from target: %s", target_buf);
      trace_running_p = 0;
      trace_running_p = 0;
      if (trace_start_stop_hook)
      if (trace_start_stop_hook)
        trace_start_stop_hook (0, from_tty);
        trace_start_stop_hook (0, from_tty);
    }
    }
  else
  else
    error ("Trace can only be run on remote targets.");
    error ("Trace can only be run on remote targets.");
}
}
 
 
unsigned long trace_running_p;
unsigned long trace_running_p;
 
 
/* tstatus command */
/* tstatus command */
static void
static void
trace_status_command (args, from_tty)
trace_status_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{                               /* STUB_COMM IS_IMPLEMENTED */
{                               /* STUB_COMM IS_IMPLEMENTED */
  if (target_is_remote ())
  if (target_is_remote ())
    {
    {
      putpkt ("qTStatus");
      putpkt ("qTStatus");
      remote_get_noisy_reply (target_buf, sizeof (target_buf));
      remote_get_noisy_reply (target_buf, sizeof (target_buf));
 
 
      if (target_buf[0] != 'T' ||
      if (target_buf[0] != 'T' ||
          (target_buf[1] != '0' && target_buf[1] != '1'))
          (target_buf[1] != '0' && target_buf[1] != '1'))
        error ("Bogus reply from target: %s", target_buf);
        error ("Bogus reply from target: %s", target_buf);
 
 
      /* exported for use by the GUI */
      /* exported for use by the GUI */
      trace_running_p = (target_buf[1] == '1');
      trace_running_p = (target_buf[1] == '1');
    }
    }
  else
  else
    error ("Trace can only be run on remote targets.");
    error ("Trace can only be run on remote targets.");
}
}
 
 
/* Worker function for the various flavors of the tfind command */
/* Worker function for the various flavors of the tfind command */
static void
static void
finish_tfind_command (char *msg,
finish_tfind_command (char *msg,
                      long sizeof_msg,
                      long sizeof_msg,
                      int from_tty)
                      int from_tty)
{
{
  int target_frameno = -1, target_tracept = -1;
  int target_frameno = -1, target_tracept = -1;
  CORE_ADDR old_frame_addr;
  CORE_ADDR old_frame_addr;
  struct symbol *old_func;
  struct symbol *old_func;
  char *reply;
  char *reply;
 
 
  old_frame_addr = FRAME_FP (get_current_frame ());
  old_frame_addr = FRAME_FP (get_current_frame ());
  old_func = find_pc_function (read_pc ());
  old_func = find_pc_function (read_pc ());
 
 
  putpkt (msg);
  putpkt (msg);
  reply = remote_get_noisy_reply (msg, sizeof_msg);
  reply = remote_get_noisy_reply (msg, sizeof_msg);
 
 
  while (reply && *reply)
  while (reply && *reply)
    switch (*reply)
    switch (*reply)
      {
      {
      case 'F':
      case 'F':
        if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
        if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
          {
          {
            /* A request for a non-existant trace frame has failed.
            /* A request for a non-existant trace frame has failed.
               Our response will be different, depending on FROM_TTY:
               Our response will be different, depending on FROM_TTY:
 
 
               If FROM_TTY is true, meaning that this command was
               If FROM_TTY is true, meaning that this command was
               typed interactively by the user, then give an error
               typed interactively by the user, then give an error
               and DO NOT change the state of traceframe_number etc.
               and DO NOT change the state of traceframe_number etc.
 
 
               However if FROM_TTY is false, meaning that we're either
               However if FROM_TTY is false, meaning that we're either
               in a script, a loop, or a user-defined command, then
               in a script, a loop, or a user-defined command, then
               DON'T give an error, but DO change the state of
               DON'T give an error, but DO change the state of
               traceframe_number etc. to invalid.
               traceframe_number etc. to invalid.
 
 
               The rationalle is that if you typed the command, you
               The rationalle is that if you typed the command, you
               might just have committed a typo or something, and you'd
               might just have committed a typo or something, and you'd
               like to NOT lose your current debugging state.  However
               like to NOT lose your current debugging state.  However
               if you're in a user-defined command or especially in a
               if you're in a user-defined command or especially in a
               loop, then you need a way to detect that the command
               loop, then you need a way to detect that the command
               failed WITHOUT aborting.  This allows you to write
               failed WITHOUT aborting.  This allows you to write
               scripts that search thru the trace buffer until the end,
               scripts that search thru the trace buffer until the end,
               and then continue on to do something else.  */
               and then continue on to do something else.  */
 
 
            if (from_tty)
            if (from_tty)
              error ("Target failed to find requested trace frame.");
              error ("Target failed to find requested trace frame.");
            else
            else
              {
              {
                if (info_verbose)
                if (info_verbose)
                  printf_filtered ("End of trace buffer.\n");
                  printf_filtered ("End of trace buffer.\n");
                /* The following will not recurse, since it's special-cased */
                /* The following will not recurse, since it's special-cased */
                trace_find_command ("-1", from_tty);
                trace_find_command ("-1", from_tty);
                reply = NULL;   /* break out of loop,
                reply = NULL;   /* break out of loop,
                                   (avoid recursive nonsense) */
                                   (avoid recursive nonsense) */
              }
              }
          }
          }
        break;
        break;
      case 'T':
      case 'T':
        if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
        if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
          error ("Target failed to find requested trace frame.");
          error ("Target failed to find requested trace frame.");
        break;
        break;
      case 'O':         /* "OK"? */
      case 'O':         /* "OK"? */
        if (reply[1] == 'K' && reply[2] == '\0')
        if (reply[1] == 'K' && reply[2] == '\0')
          reply += 2;
          reply += 2;
        else
        else
          error ("Bogus reply from target: %s", reply);
          error ("Bogus reply from target: %s", reply);
        break;
        break;
      default:
      default:
        error ("Bogus reply from target: %s", reply);
        error ("Bogus reply from target: %s", reply);
      }
      }
 
 
  flush_cached_frames ();
  flush_cached_frames ();
  registers_changed ();
  registers_changed ();
  select_frame (get_current_frame (), 0);
  select_frame (get_current_frame (), 0);
  set_traceframe_num (target_frameno);
  set_traceframe_num (target_frameno);
  set_tracepoint_num (target_tracept);
  set_tracepoint_num (target_tracept);
  if (target_frameno == -1)
  if (target_frameno == -1)
    set_traceframe_context (-1);
    set_traceframe_context (-1);
  else
  else
    set_traceframe_context (read_pc ());
    set_traceframe_context (read_pc ());
 
 
  if (from_tty)
  if (from_tty)
    {
    {
      int source_only;
      int source_only;
 
 
      /* NOTE: in immitation of the step command, try to determine
      /* NOTE: in immitation of the step command, try to determine
         whether we have made a transition from one function to another.
         whether we have made a transition from one function to another.
         If so, we'll print the "stack frame" (ie. the new function and
         If so, we'll print the "stack frame" (ie. the new function and
         it's arguments) -- otherwise we'll just show the new source line.
         it's arguments) -- otherwise we'll just show the new source line.
 
 
         This determination is made by checking (1) whether the current
         This determination is made by checking (1) whether the current
         function has changed, and (2) whether the current FP has changed.
         function has changed, and (2) whether the current FP has changed.
         Hack: if the FP wasn't collected, either at the current or the
         Hack: if the FP wasn't collected, either at the current or the
         previous frame, assume that the FP has NOT changed.  */
         previous frame, assume that the FP has NOT changed.  */
 
 
      if (old_func == find_pc_function (read_pc ()) &&
      if (old_func == find_pc_function (read_pc ()) &&
          (old_frame_addr == 0 ||
          (old_frame_addr == 0 ||
           FRAME_FP (get_current_frame ()) == 0 ||
           FRAME_FP (get_current_frame ()) == 0 ||
           old_frame_addr == FRAME_FP (get_current_frame ())))
           old_frame_addr == FRAME_FP (get_current_frame ())))
        source_only = -1;
        source_only = -1;
      else
      else
        source_only = 1;
        source_only = 1;
 
 
      print_stack_frame (selected_frame, selected_frame_level, source_only);
      print_stack_frame (selected_frame, selected_frame_level, source_only);
      do_displays ();
      do_displays ();
    }
    }
}
}
 
 
/* trace_find_command takes a trace frame number n,
/* trace_find_command takes a trace frame number n,
   sends "QTFrame:<n>" to the target,
   sends "QTFrame:<n>" to the target,
   and accepts a reply that may contain several optional pieces
   and accepts a reply that may contain several optional pieces
   of information: a frame number, a tracepoint number, and an
   of information: a frame number, a tracepoint number, and an
   indication of whether this is a trap frame or a stepping frame.
   indication of whether this is a trap frame or a stepping frame.
 
 
   The minimal response is just "OK" (which indicates that the
   The minimal response is just "OK" (which indicates that the
   target does not give us a frame number or a tracepoint number).
   target does not give us a frame number or a tracepoint number).
   Instead of that, the target may send us a string containing
   Instead of that, the target may send us a string containing
   any combination of:
   any combination of:
   F<hexnum>    (gives the selected frame number)
   F<hexnum>    (gives the selected frame number)
   T<hexnum>    (gives the selected tracepoint number)
   T<hexnum>    (gives the selected tracepoint number)
 */
 */
 
 
/* tfind command */
/* tfind command */
static void
static void
trace_find_command (args, from_tty)
trace_find_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{                               /* STUB_COMM PART_IMPLEMENTED */
{                               /* STUB_COMM PART_IMPLEMENTED */
  /* this should only be called with a numeric argument */
  /* this should only be called with a numeric argument */
  int frameno = -1;
  int frameno = -1;
 
 
  if (target_is_remote ())
  if (target_is_remote ())
    {
    {
      if (trace_find_hook)
      if (trace_find_hook)
        trace_find_hook (args, from_tty);
        trace_find_hook (args, from_tty);
 
 
      if (args == 0 || *args == 0)
      if (args == 0 || *args == 0)
        {                       /* TFIND with no args means find NEXT trace frame. */
        {                       /* TFIND with no args means find NEXT trace frame. */
          if (traceframe_number == -1)
          if (traceframe_number == -1)
            frameno = 0; /* "next" is first one */
            frameno = 0; /* "next" is first one */
          else
          else
            frameno = traceframe_number + 1;
            frameno = traceframe_number + 1;
        }
        }
      else if (0 == strcmp (args, "-"))
      else if (0 == strcmp (args, "-"))
        {
        {
          if (traceframe_number == -1)
          if (traceframe_number == -1)
            error ("not debugging trace buffer");
            error ("not debugging trace buffer");
          else if (from_tty && traceframe_number == 0)
          else if (from_tty && traceframe_number == 0)
            error ("already at start of trace buffer");
            error ("already at start of trace buffer");
 
 
          frameno = traceframe_number - 1;
          frameno = traceframe_number - 1;
        }
        }
      else
      else
        frameno = parse_and_eval_address (args);
        frameno = parse_and_eval_address (args);
 
 
      if (frameno < -1)
      if (frameno < -1)
        error ("invalid input (%d is less than zero)", frameno);
        error ("invalid input (%d is less than zero)", frameno);
 
 
      sprintf (target_buf, "QTFrame:%x", frameno);
      sprintf (target_buf, "QTFrame:%x", frameno);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
    }
    }
  else
  else
    error ("Trace can only be run on remote targets.");
    error ("Trace can only be run on remote targets.");
}
}
 
 
/* tfind end */
/* tfind end */
static void
static void
trace_find_end_command (args, from_tty)
trace_find_end_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  trace_find_command ("-1", from_tty);
  trace_find_command ("-1", from_tty);
}
}
 
 
/* tfind none */
/* tfind none */
static void
static void
trace_find_none_command (args, from_tty)
trace_find_none_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  trace_find_command ("-1", from_tty);
  trace_find_command ("-1", from_tty);
}
}
 
 
/* tfind start */
/* tfind start */
static void
static void
trace_find_start_command (args, from_tty)
trace_find_start_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  trace_find_command ("0", from_tty);
  trace_find_command ("0", from_tty);
}
}
 
 
/* tfind pc command */
/* tfind pc command */
static void
static void
trace_find_pc_command (args, from_tty)
trace_find_pc_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{                               /* STUB_COMM PART_IMPLEMENTED */
{                               /* STUB_COMM PART_IMPLEMENTED */
  CORE_ADDR pc;
  CORE_ADDR pc;
  char tmp[40];
  char tmp[40];
 
 
  if (target_is_remote ())
  if (target_is_remote ())
    {
    {
      if (args == 0 || *args == 0)
      if (args == 0 || *args == 0)
        pc = read_pc ();        /* default is current pc */
        pc = read_pc ();        /* default is current pc */
      else
      else
        pc = parse_and_eval_address (args);
        pc = parse_and_eval_address (args);
 
 
      sprintf_vma (tmp, pc);
      sprintf_vma (tmp, pc);
      sprintf (target_buf, "QTFrame:pc:%s", tmp);
      sprintf (target_buf, "QTFrame:pc:%s", tmp);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
    }
    }
  else
  else
    error ("Trace can only be run on remote targets.");
    error ("Trace can only be run on remote targets.");
}
}
 
 
/* tfind tracepoint command */
/* tfind tracepoint command */
static void
static void
trace_find_tracepoint_command (args, from_tty)
trace_find_tracepoint_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{                               /* STUB_COMM PART_IMPLEMENTED */
{                               /* STUB_COMM PART_IMPLEMENTED */
  int tdp;
  int tdp;
 
 
  if (target_is_remote ())
  if (target_is_remote ())
    {
    {
      if (args == 0 || *args == 0)
      if (args == 0 || *args == 0)
        if (tracepoint_number == -1)
        if (tracepoint_number == -1)
          error ("No current tracepoint -- please supply an argument.");
          error ("No current tracepoint -- please supply an argument.");
        else
        else
          tdp = tracepoint_number;      /* default is current TDP */
          tdp = tracepoint_number;      /* default is current TDP */
      else
      else
        tdp = parse_and_eval_address (args);
        tdp = parse_and_eval_address (args);
 
 
      sprintf (target_buf, "QTFrame:tdp:%x", tdp);
      sprintf (target_buf, "QTFrame:tdp:%x", tdp);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
    }
    }
  else
  else
    error ("Trace can only be run on remote targets.");
    error ("Trace can only be run on remote targets.");
}
}
 
 
/* TFIND LINE command:
/* TFIND LINE command:
 
 
   This command will take a sourceline for argument, just like BREAK
   This command will take a sourceline for argument, just like BREAK
   or TRACE (ie. anything that "decode_line_1" can handle).
   or TRACE (ie. anything that "decode_line_1" can handle).
 
 
   With no argument, this command will find the next trace frame
   With no argument, this command will find the next trace frame
   corresponding to a source line OTHER THAN THE CURRENT ONE.  */
   corresponding to a source line OTHER THAN THE CURRENT ONE.  */
 
 
static void
static void
trace_find_line_command (args, from_tty)
trace_find_line_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{                               /* STUB_COMM PART_IMPLEMENTED */
{                               /* STUB_COMM PART_IMPLEMENTED */
  static CORE_ADDR start_pc, end_pc;
  static CORE_ADDR start_pc, end_pc;
  struct symtabs_and_lines sals;
  struct symtabs_and_lines sals;
  struct symtab_and_line sal;
  struct symtab_and_line sal;
  struct cleanup *old_chain;
  struct cleanup *old_chain;
  char   startpc_str[40], endpc_str[40];
  char   startpc_str[40], endpc_str[40];
 
 
  if (target_is_remote ())
  if (target_is_remote ())
    {
    {
      if (args == 0 || *args == 0)
      if (args == 0 || *args == 0)
        {
        {
          sal = find_pc_line ((get_current_frame ())->pc, 0);
          sal = find_pc_line ((get_current_frame ())->pc, 0);
          sals.nelts = 1;
          sals.nelts = 1;
          sals.sals = (struct symtab_and_line *)
          sals.sals = (struct symtab_and_line *)
            xmalloc (sizeof (struct symtab_and_line));
            xmalloc (sizeof (struct symtab_and_line));
          sals.sals[0] = sal;
          sals.sals[0] = sal;
        }
        }
      else
      else
        {
        {
          sals = decode_line_spec (args, 1);
          sals = decode_line_spec (args, 1);
          sal = sals.sals[0];
          sal = sals.sals[0];
        }
        }
 
 
      old_chain = make_cleanup (free, sals.sals);
      old_chain = make_cleanup (free, sals.sals);
      if (sal.symtab == 0)
      if (sal.symtab == 0)
        {
        {
          printf_filtered ("TFIND: No line number information available");
          printf_filtered ("TFIND: No line number information available");
          if (sal.pc != 0)
          if (sal.pc != 0)
            {
            {
              /* This is useful for "info line *0x7f34".  If we can't tell the
              /* This is useful for "info line *0x7f34".  If we can't tell the
                 user about a source line, at least let them have the symbolic
                 user about a source line, at least let them have the symbolic
                 address.  */
                 address.  */
              printf_filtered (" for address ");
              printf_filtered (" for address ");
              wrap_here ("  ");
              wrap_here ("  ");
              print_address (sal.pc, gdb_stdout);
              print_address (sal.pc, gdb_stdout);
              printf_filtered (";\n -- will attempt to find by PC. \n");
              printf_filtered (";\n -- will attempt to find by PC. \n");
            }
            }
          else
          else
            {
            {
              printf_filtered (".\n");
              printf_filtered (".\n");
              return;           /* no line, no PC; what can we do? */
              return;           /* no line, no PC; what can we do? */
            }
            }
        }
        }
      else if (sal.line > 0
      else if (sal.line > 0
               && find_line_pc_range (sal, &start_pc, &end_pc))
               && find_line_pc_range (sal, &start_pc, &end_pc))
        {
        {
          if (start_pc == end_pc)
          if (start_pc == end_pc)
            {
            {
              printf_filtered ("Line %d of \"%s\"",
              printf_filtered ("Line %d of \"%s\"",
                               sal.line, sal.symtab->filename);
                               sal.line, sal.symtab->filename);
              wrap_here ("  ");
              wrap_here ("  ");
              printf_filtered (" is at address ");
              printf_filtered (" is at address ");
              print_address (start_pc, gdb_stdout);
              print_address (start_pc, gdb_stdout);
              wrap_here ("  ");
              wrap_here ("  ");
              printf_filtered (" but contains no code.\n");
              printf_filtered (" but contains no code.\n");
              sal = find_pc_line (start_pc, 0);
              sal = find_pc_line (start_pc, 0);
              if (sal.line > 0 &&
              if (sal.line > 0 &&
                  find_line_pc_range (sal, &start_pc, &end_pc) &&
                  find_line_pc_range (sal, &start_pc, &end_pc) &&
                  start_pc != end_pc)
                  start_pc != end_pc)
                printf_filtered ("Attempting to find line %d instead.\n",
                printf_filtered ("Attempting to find line %d instead.\n",
                                 sal.line);
                                 sal.line);
              else
              else
                error ("Cannot find a good line.");
                error ("Cannot find a good line.");
            }
            }
        }
        }
      else
      else
        /* Is there any case in which we get here, and have an address
        /* Is there any case in which we get here, and have an address
           which the user would want to see?  If we have debugging symbols
           which the user would want to see?  If we have debugging symbols
           and no line numbers?  */
           and no line numbers?  */
        error ("Line number %d is out of range for \"%s\".\n",
        error ("Line number %d is out of range for \"%s\".\n",
               sal.line, sal.symtab->filename);
               sal.line, sal.symtab->filename);
 
 
      sprintf_vma (startpc_str, start_pc);
      sprintf_vma (startpc_str, start_pc);
      sprintf_vma (endpc_str, end_pc - 1);
      sprintf_vma (endpc_str, end_pc - 1);
      if (args && *args)        /* find within range of stated line */
      if (args && *args)        /* find within range of stated line */
        sprintf (target_buf, "QTFrame:range:%s:%s", startpc_str, endpc_str);
        sprintf (target_buf, "QTFrame:range:%s:%s", startpc_str, endpc_str);
      else                      /* find OUTSIDE OF range of CURRENT line */
      else                      /* find OUTSIDE OF range of CURRENT line */
        sprintf (target_buf, "QTFrame:outside:%s:%s", startpc_str, endpc_str);
        sprintf (target_buf, "QTFrame:outside:%s:%s", startpc_str, endpc_str);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
      do_cleanups (old_chain);
      do_cleanups (old_chain);
    }
    }
  else
  else
    error ("Trace can only be run on remote targets.");
    error ("Trace can only be run on remote targets.");
}
}
 
 
/* tfind range command */
/* tfind range command */
static void
static void
trace_find_range_command (args, from_tty)
trace_find_range_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  static CORE_ADDR start, stop;
  static CORE_ADDR start, stop;
  char start_str[40], stop_str[40];
  char start_str[40], stop_str[40];
  char *tmp;
  char *tmp;
 
 
  if (target_is_remote ())
  if (target_is_remote ())
    {
    {
      if (args == 0 || *args == 0)
      if (args == 0 || *args == 0)
        {               /* XXX FIXME: what should default behavior be? */
        {               /* XXX FIXME: what should default behavior be? */
          printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
          printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
          return;
          return;
        }
        }
 
 
      if (0 != (tmp = strchr (args, ',')))
      if (0 != (tmp = strchr (args, ',')))
        {
        {
          *tmp++ = '\0';        /* terminate start address */
          *tmp++ = '\0';        /* terminate start address */
          while (isspace ((int) *tmp))
          while (isspace ((int) *tmp))
            tmp++;
            tmp++;
          start = parse_and_eval_address (args);
          start = parse_and_eval_address (args);
          stop = parse_and_eval_address (tmp);
          stop = parse_and_eval_address (tmp);
        }
        }
      else
      else
        {                       /* no explicit end address? */
        {                       /* no explicit end address? */
          start = parse_and_eval_address (args);
          start = parse_and_eval_address (args);
          stop = start + 1;     /* ??? */
          stop = start + 1;     /* ??? */
        }
        }
 
 
      sprintf_vma (start_str, start);
      sprintf_vma (start_str, start);
      sprintf_vma (stop_str, stop);
      sprintf_vma (stop_str, stop);
      sprintf (target_buf, "QTFrame:range:%s:%s", start_str, stop_str);
      sprintf (target_buf, "QTFrame:range:%s:%s", start_str, stop_str);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
    }
    }
  else
  else
    error ("Trace can only be run on remote targets.");
    error ("Trace can only be run on remote targets.");
}
}
 
 
/* tfind outside command */
/* tfind outside command */
static void
static void
trace_find_outside_command (args, from_tty)
trace_find_outside_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  CORE_ADDR start, stop;
  CORE_ADDR start, stop;
  char start_str[40], stop_str[40];
  char start_str[40], stop_str[40];
  char *tmp;
  char *tmp;
 
 
  if (target_is_remote ())
  if (target_is_remote ())
    {
    {
      if (args == 0 || *args == 0)
      if (args == 0 || *args == 0)
        {               /* XXX FIXME: what should default behavior be? */
        {               /* XXX FIXME: what should default behavior be? */
          printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
          printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
          return;
          return;
        }
        }
 
 
      if (0 != (tmp = strchr (args, ',')))
      if (0 != (tmp = strchr (args, ',')))
        {
        {
          *tmp++ = '\0';        /* terminate start address */
          *tmp++ = '\0';        /* terminate start address */
          while (isspace ((int) *tmp))
          while (isspace ((int) *tmp))
            tmp++;
            tmp++;
          start = parse_and_eval_address (args);
          start = parse_and_eval_address (args);
          stop = parse_and_eval_address (tmp);
          stop = parse_and_eval_address (tmp);
        }
        }
      else
      else
        {                       /* no explicit end address? */
        {                       /* no explicit end address? */
          start = parse_and_eval_address (args);
          start = parse_and_eval_address (args);
          stop = start + 1;     /* ??? */
          stop = start + 1;     /* ??? */
        }
        }
 
 
      sprintf_vma (start_str, start);
      sprintf_vma (start_str, start);
      sprintf_vma (stop_str, stop);
      sprintf_vma (stop_str, stop);
      sprintf (target_buf, "QTFrame:outside:%s:%s", start_str, stop_str);
      sprintf (target_buf, "QTFrame:outside:%s:%s", start_str, stop_str);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
      finish_tfind_command (target_buf, sizeof (target_buf), from_tty);
    }
    }
  else
  else
    error ("Trace can only be run on remote targets.");
    error ("Trace can only be run on remote targets.");
}
}
 
 
/* save-tracepoints command */
/* save-tracepoints command */
static void
static void
tracepoint_save_command (args, from_tty)
tracepoint_save_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  struct tracepoint *tp;
  struct tracepoint *tp;
  struct action_line *line;
  struct action_line *line;
  FILE *fp;
  FILE *fp;
  char *i1 = "    ", *i2 = "      ";
  char *i1 = "    ", *i2 = "      ";
  char *indent, *actionline;
  char *indent, *actionline;
  char tmp[40];
  char tmp[40];
 
 
  if (args == 0 || *args == 0)
  if (args == 0 || *args == 0)
    error ("Argument required (file name in which to save tracepoints");
    error ("Argument required (file name in which to save tracepoints");
 
 
  if (tracepoint_chain == 0)
  if (tracepoint_chain == 0)
    {
    {
      warning ("save-tracepoints: no tracepoints to save.\n");
      warning ("save-tracepoints: no tracepoints to save.\n");
      return;
      return;
    }
    }
 
 
  if (!(fp = fopen (args, "w")))
  if (!(fp = fopen (args, "w")))
    error ("Unable to open file '%s' for saving tracepoints");
    error ("Unable to open file '%s' for saving tracepoints");
 
 
  ALL_TRACEPOINTS (tp)
  ALL_TRACEPOINTS (tp)
  {
  {
    if (tp->addr_string)
    if (tp->addr_string)
      fprintf (fp, "trace %s\n", tp->addr_string);
      fprintf (fp, "trace %s\n", tp->addr_string);
    else
    else
      {
      {
        sprintf_vma (tmp, tp->address);
        sprintf_vma (tmp, tp->address);
        fprintf (fp, "trace *0x%s\n", tmp);
        fprintf (fp, "trace *0x%s\n", tmp);
      }
      }
 
 
    if (tp->pass_count)
    if (tp->pass_count)
      fprintf (fp, "  passcount %d\n", tp->pass_count);
      fprintf (fp, "  passcount %d\n", tp->pass_count);
 
 
    if (tp->actions)
    if (tp->actions)
      {
      {
        fprintf (fp, "  actions\n");
        fprintf (fp, "  actions\n");
        indent = i1;
        indent = i1;
        for (line = tp->actions; line; line = line->next)
        for (line = tp->actions; line; line = line->next)
          {
          {
            struct cmd_list_element *cmd;
            struct cmd_list_element *cmd;
 
 
            QUIT;               /* allow user to bail out with ^C */
            QUIT;               /* allow user to bail out with ^C */
            actionline = line->action;
            actionline = line->action;
            while (isspace ((int) *actionline))
            while (isspace ((int) *actionline))
              actionline++;
              actionline++;
 
 
            fprintf (fp, "%s%s\n", indent, actionline);
            fprintf (fp, "%s%s\n", indent, actionline);
            if (*actionline != '#')     /* skip for comment lines */
            if (*actionline != '#')     /* skip for comment lines */
              {
              {
                cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
                cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
                if (cmd == 0)
                if (cmd == 0)
                  error ("Bad action list item: %s", actionline);
                  error ("Bad action list item: %s", actionline);
                if (cmd->function.cfunc == while_stepping_pseudocommand)
                if (cmd->function.cfunc == while_stepping_pseudocommand)
                  indent = i2;
                  indent = i2;
                else if (cmd->function.cfunc == end_actions_pseudocommand)
                else if (cmd->function.cfunc == end_actions_pseudocommand)
                  indent = i1;
                  indent = i1;
              }
              }
          }
          }
      }
      }
  }
  }
  fclose (fp);
  fclose (fp);
  if (from_tty)
  if (from_tty)
    printf_filtered ("Tracepoints saved to file '%s'.\n", args);
    printf_filtered ("Tracepoints saved to file '%s'.\n", args);
  return;
  return;
}
}
 
 
/* info scope command: list the locals for a scope.  */
/* info scope command: list the locals for a scope.  */
static void
static void
scope_info (args, from_tty)
scope_info (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  struct symtabs_and_lines sals;
  struct symtabs_and_lines sals;
  struct symbol *sym;
  struct symbol *sym;
  struct minimal_symbol *msym;
  struct minimal_symbol *msym;
  struct block *block;
  struct block *block;
  char **canonical, *symname, *save_args = args;
  char **canonical, *symname, *save_args = args;
  int i, j, nsyms, count = 0;
  int i, j, nsyms, count = 0;
 
 
  if (args == 0 || *args == 0)
  if (args == 0 || *args == 0)
    error ("requires an argument (function, line or *addr) to define a scope");
    error ("requires an argument (function, line or *addr) to define a scope");
 
 
  sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
  sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
  if (sals.nelts == 0)
  if (sals.nelts == 0)
    return;                     /* presumably decode_line_1 has already warned */
    return;                     /* presumably decode_line_1 has already warned */
 
 
  /* Resolve line numbers to PC */
  /* Resolve line numbers to PC */
  resolve_sal_pc (&sals.sals[0]);
  resolve_sal_pc (&sals.sals[0]);
  block = block_for_pc (sals.sals[0].pc);
  block = block_for_pc (sals.sals[0].pc);
 
 
  while (block != 0)
  while (block != 0)
    {
    {
      QUIT;                     /* allow user to bail out with ^C */
      QUIT;                     /* allow user to bail out with ^C */
      nsyms = BLOCK_NSYMS (block);
      nsyms = BLOCK_NSYMS (block);
      for (i = 0; i < nsyms; i++)
      for (i = 0; i < nsyms; i++)
        {
        {
          QUIT;                 /* allow user to bail out with ^C */
          QUIT;                 /* allow user to bail out with ^C */
          if (count == 0)
          if (count == 0)
            printf_filtered ("Scope for %s:\n", save_args);
            printf_filtered ("Scope for %s:\n", save_args);
          count++;
          count++;
          sym = BLOCK_SYM (block, i);
          sym = BLOCK_SYM (block, i);
          symname = SYMBOL_NAME (sym);
          symname = SYMBOL_NAME (sym);
          if (symname == NULL || *symname == '\0')
          if (symname == NULL || *symname == '\0')
            continue;           /* probably botched, certainly useless */
            continue;           /* probably botched, certainly useless */
 
 
          printf_filtered ("Symbol %s is ", symname);
          printf_filtered ("Symbol %s is ", symname);
          switch (SYMBOL_CLASS (sym))
          switch (SYMBOL_CLASS (sym))
            {
            {
            default:
            default:
            case LOC_UNDEF:     /* messed up symbol? */
            case LOC_UNDEF:     /* messed up symbol? */
              printf_filtered ("a bogus symbol, class %d.\n",
              printf_filtered ("a bogus symbol, class %d.\n",
                               SYMBOL_CLASS (sym));
                               SYMBOL_CLASS (sym));
              count--;          /* don't count this one */
              count--;          /* don't count this one */
              continue;
              continue;
            case LOC_CONST:
            case LOC_CONST:
              printf_filtered ("a constant with value %ld (0x%lx)",
              printf_filtered ("a constant with value %ld (0x%lx)",
                               SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
                               SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
              break;
              break;
            case LOC_CONST_BYTES:
            case LOC_CONST_BYTES:
              printf_filtered ("constant bytes: ");
              printf_filtered ("constant bytes: ");
              if (SYMBOL_TYPE (sym))
              if (SYMBOL_TYPE (sym))
                for (j = 0; j < TYPE_LENGTH (SYMBOL_TYPE (sym)); j++)
                for (j = 0; j < TYPE_LENGTH (SYMBOL_TYPE (sym)); j++)
                  fprintf_filtered (gdb_stdout, " %02x",
                  fprintf_filtered (gdb_stdout, " %02x",
                                    (unsigned) SYMBOL_VALUE_BYTES (sym)[j]);
                                    (unsigned) SYMBOL_VALUE_BYTES (sym)[j]);
              break;
              break;
            case LOC_STATIC:
            case LOC_STATIC:
              printf_filtered ("in static storage at address ");
              printf_filtered ("in static storage at address ");
              print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
              print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
              break;
              break;
            case LOC_REGISTER:
            case LOC_REGISTER:
              printf_filtered ("a local variable in register $%s",
              printf_filtered ("a local variable in register $%s",
                               REGISTER_NAME (SYMBOL_VALUE (sym)));
                               REGISTER_NAME (SYMBOL_VALUE (sym)));
              break;
              break;
            case LOC_ARG:
            case LOC_ARG:
            case LOC_LOCAL_ARG:
            case LOC_LOCAL_ARG:
              printf_filtered ("an argument at stack/frame offset %ld",
              printf_filtered ("an argument at stack/frame offset %ld",
                               SYMBOL_VALUE (sym));
                               SYMBOL_VALUE (sym));
              break;
              break;
            case LOC_LOCAL:
            case LOC_LOCAL:
              printf_filtered ("a local variable at frame offset %ld",
              printf_filtered ("a local variable at frame offset %ld",
                               SYMBOL_VALUE (sym));
                               SYMBOL_VALUE (sym));
              break;
              break;
            case LOC_REF_ARG:
            case LOC_REF_ARG:
              printf_filtered ("a reference argument at offset %ld",
              printf_filtered ("a reference argument at offset %ld",
                               SYMBOL_VALUE (sym));
                               SYMBOL_VALUE (sym));
              break;
              break;
            case LOC_REGPARM:
            case LOC_REGPARM:
              printf_filtered ("an argument in register $%s",
              printf_filtered ("an argument in register $%s",
                               REGISTER_NAME (SYMBOL_VALUE (sym)));
                               REGISTER_NAME (SYMBOL_VALUE (sym)));
              break;
              break;
            case LOC_REGPARM_ADDR:
            case LOC_REGPARM_ADDR:
              printf_filtered ("the address of an argument, in register $%s",
              printf_filtered ("the address of an argument, in register $%s",
                               REGISTER_NAME (SYMBOL_VALUE (sym)));
                               REGISTER_NAME (SYMBOL_VALUE (sym)));
              break;
              break;
            case LOC_TYPEDEF:
            case LOC_TYPEDEF:
              printf_filtered ("a typedef.\n");
              printf_filtered ("a typedef.\n");
              continue;
              continue;
            case LOC_LABEL:
            case LOC_LABEL:
              printf_filtered ("a label at address ");
              printf_filtered ("a label at address ");
              print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
              print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
              break;
              break;
            case LOC_BLOCK:
            case LOC_BLOCK:
              printf_filtered ("a function at address ");
              printf_filtered ("a function at address ");
              print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
              print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
                                     gdb_stdout);
                                     gdb_stdout);
              break;
              break;
            case LOC_BASEREG:
            case LOC_BASEREG:
              printf_filtered ("a variable at offset %ld from register $%s",
              printf_filtered ("a variable at offset %ld from register $%s",
                               SYMBOL_VALUE (sym),
                               SYMBOL_VALUE (sym),
                               REGISTER_NAME (SYMBOL_BASEREG (sym)));
                               REGISTER_NAME (SYMBOL_BASEREG (sym)));
              break;
              break;
            case LOC_BASEREG_ARG:
            case LOC_BASEREG_ARG:
              printf_filtered ("an argument at offset %ld from register $%s",
              printf_filtered ("an argument at offset %ld from register $%s",
                               SYMBOL_VALUE (sym),
                               SYMBOL_VALUE (sym),
                               REGISTER_NAME (SYMBOL_BASEREG (sym)));
                               REGISTER_NAME (SYMBOL_BASEREG (sym)));
              break;
              break;
            case LOC_UNRESOLVED:
            case LOC_UNRESOLVED:
              msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
              msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
              if (msym == NULL)
              if (msym == NULL)
                printf_filtered ("Unresolved Static");
                printf_filtered ("Unresolved Static");
              else
              else
                {
                {
                  printf_filtered ("static storage at address ");
                  printf_filtered ("static storage at address ");
                  print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1,
                  print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1,
                                         gdb_stdout);
                                         gdb_stdout);
                }
                }
              break;
              break;
            case LOC_OPTIMIZED_OUT:
            case LOC_OPTIMIZED_OUT:
              printf_filtered ("optimized out.\n");
              printf_filtered ("optimized out.\n");
              continue;
              continue;
            }
            }
          if (SYMBOL_TYPE (sym))
          if (SYMBOL_TYPE (sym))
            printf_filtered (", length %d.\n",
            printf_filtered (", length %d.\n",
                           TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
                           TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
        }
        }
      if (BLOCK_FUNCTION (block))
      if (BLOCK_FUNCTION (block))
        break;
        break;
      else
      else
        block = BLOCK_SUPERBLOCK (block);
        block = BLOCK_SUPERBLOCK (block);
    }
    }
  if (count <= 0)
  if (count <= 0)
    printf_filtered ("Scope for %s contains no locals or arguments.\n",
    printf_filtered ("Scope for %s contains no locals or arguments.\n",
                     save_args);
                     save_args);
}
}
 
 
/* worker function (cleanup) */
/* worker function (cleanup) */
static void
static void
replace_comma (comma)
replace_comma (comma)
     char *comma;
     char *comma;
{
{
  *comma = ',';
  *comma = ',';
}
}
 
 
/* tdump command */
/* tdump command */
static void
static void
trace_dump_command (args, from_tty)
trace_dump_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  struct tracepoint *t;
  struct tracepoint *t;
  struct action_line *action;
  struct action_line *action;
  char *action_exp, *next_comma;
  char *action_exp, *next_comma;
  struct cleanup *old_cleanups;
  struct cleanup *old_cleanups;
  int stepping_actions = 0;
  int stepping_actions = 0;
  int stepping_frame = 0;
  int stepping_frame = 0;
 
 
  if (!target_is_remote ())
  if (!target_is_remote ())
    {
    {
      error ("Trace can only be run on remote targets.");
      error ("Trace can only be run on remote targets.");
      return;
      return;
    }
    }
 
 
  if (tracepoint_number == -1)
  if (tracepoint_number == -1)
    {
    {
      warning ("No current trace frame.");
      warning ("No current trace frame.");
      return;
      return;
    }
    }
 
 
  ALL_TRACEPOINTS (t)
  ALL_TRACEPOINTS (t)
    if (t->number == tracepoint_number)
    if (t->number == tracepoint_number)
    break;
    break;
 
 
  if (t == NULL)
  if (t == NULL)
    error ("No known tracepoint matches 'current' tracepoint #%d.",
    error ("No known tracepoint matches 'current' tracepoint #%d.",
           tracepoint_number);
           tracepoint_number);
 
 
  old_cleanups = make_cleanup (null_cleanup, NULL);
  old_cleanups = make_cleanup (null_cleanup, NULL);
 
 
  printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
  printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
                   tracepoint_number, traceframe_number);
                   tracepoint_number, traceframe_number);
 
 
  /* The current frame is a trap frame if the frame PC is equal
  /* The current frame is a trap frame if the frame PC is equal
     to the tracepoint PC.  If not, then the current frame was
     to the tracepoint PC.  If not, then the current frame was
     collected during single-stepping.  */
     collected during single-stepping.  */
 
 
  stepping_frame = (t->address != read_pc ());
  stepping_frame = (t->address != read_pc ());
 
 
  for (action = t->actions; action; action = action->next)
  for (action = t->actions; action; action = action->next)
    {
    {
      struct cmd_list_element *cmd;
      struct cmd_list_element *cmd;
 
 
      QUIT;                     /* allow user to bail out with ^C */
      QUIT;                     /* allow user to bail out with ^C */
      action_exp = action->action;
      action_exp = action->action;
      while (isspace ((int) *action_exp))
      while (isspace ((int) *action_exp))
        action_exp++;
        action_exp++;
 
 
      /* The collection actions to be done while stepping are
      /* The collection actions to be done while stepping are
         bracketed by the commands "while-stepping" and "end".  */
         bracketed by the commands "while-stepping" and "end".  */
 
 
      if (*action_exp == '#')   /* comment line */
      if (*action_exp == '#')   /* comment line */
        continue;
        continue;
 
 
      cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
      cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
      if (cmd == 0)
      if (cmd == 0)
        error ("Bad action list item: %s", action_exp);
        error ("Bad action list item: %s", action_exp);
 
 
      if (cmd->function.cfunc == while_stepping_pseudocommand)
      if (cmd->function.cfunc == while_stepping_pseudocommand)
        stepping_actions = 1;
        stepping_actions = 1;
      else if (cmd->function.cfunc == end_actions_pseudocommand)
      else if (cmd->function.cfunc == end_actions_pseudocommand)
        stepping_actions = 0;
        stepping_actions = 0;
      else if (cmd->function.cfunc == collect_pseudocommand)
      else if (cmd->function.cfunc == collect_pseudocommand)
        {
        {
          /* Display the collected data.
          /* Display the collected data.
             For the trap frame, display only what was collected at the trap.
             For the trap frame, display only what was collected at the trap.
             Likewise for stepping frames, display only what was collected
             Likewise for stepping frames, display only what was collected
             while stepping.  This means that the two boolean variables,
             while stepping.  This means that the two boolean variables,
             STEPPING_FRAME and STEPPING_ACTIONS should be equal.  */
             STEPPING_FRAME and STEPPING_ACTIONS should be equal.  */
          if (stepping_frame == stepping_actions)
          if (stepping_frame == stepping_actions)
            {
            {
              do
              do
                {               /* repeat over a comma-separated list */
                {               /* repeat over a comma-separated list */
                  QUIT;         /* allow user to bail out with ^C */
                  QUIT;         /* allow user to bail out with ^C */
                  if (*action_exp == ',')
                  if (*action_exp == ',')
                    action_exp++;
                    action_exp++;
                  while (isspace ((int) *action_exp))
                  while (isspace ((int) *action_exp))
                    action_exp++;
                    action_exp++;
 
 
                  next_comma = strchr (action_exp, ',');
                  next_comma = strchr (action_exp, ',');
 
 
                  if (0 == strncasecmp (action_exp, "$reg", 4))
                  if (0 == strncasecmp (action_exp, "$reg", 4))
                    registers_info (NULL, from_tty);
                    registers_info (NULL, from_tty);
                  else if (0 == strncasecmp (action_exp, "$loc", 4))
                  else if (0 == strncasecmp (action_exp, "$loc", 4))
                    locals_info (NULL, from_tty);
                    locals_info (NULL, from_tty);
                  else if (0 == strncasecmp (action_exp, "$arg", 4))
                  else if (0 == strncasecmp (action_exp, "$arg", 4))
                    args_info (NULL, from_tty);
                    args_info (NULL, from_tty);
                  else
                  else
                    {           /* variable */
                    {           /* variable */
                      if (next_comma)
                      if (next_comma)
                        {
                        {
                          make_cleanup (replace_comma, next_comma);
                          make_cleanup (replace_comma, next_comma);
                          *next_comma = '\0';
                          *next_comma = '\0';
                        }
                        }
                      printf_filtered ("%s = ", action_exp);
                      printf_filtered ("%s = ", action_exp);
                      output_command (action_exp, from_tty);
                      output_command (action_exp, from_tty);
                      printf_filtered ("\n");
                      printf_filtered ("\n");
                    }
                    }
                  if (next_comma)
                  if (next_comma)
                    *next_comma = ',';
                    *next_comma = ',';
                  action_exp = next_comma;
                  action_exp = next_comma;
                }
                }
              while (action_exp && *action_exp == ',');
              while (action_exp && *action_exp == ',');
            }
            }
        }
        }
    }
    }
  discard_cleanups (old_cleanups);
  discard_cleanups (old_cleanups);
}
}
 
 
/* Convert the memory pointed to by mem into hex, placing result in buf.
/* Convert the memory pointed to by mem into hex, placing result in buf.
 * Return a pointer to the last char put in buf (null)
 * Return a pointer to the last char put in buf (null)
 * "stolen" from sparc-stub.c
 * "stolen" from sparc-stub.c
 */
 */
 
 
static const char hexchars[] = "0123456789abcdef";
static const char hexchars[] = "0123456789abcdef";
 
 
static unsigned char *
static unsigned char *
mem2hex (mem, buf, count)
mem2hex (mem, buf, count)
     unsigned char *mem;
     unsigned char *mem;
     unsigned char *buf;
     unsigned char *buf;
     int count;
     int count;
{
{
  unsigned char ch;
  unsigned char ch;
 
 
  while (count-- > 0)
  while (count-- > 0)
    {
    {
      ch = *mem++;
      ch = *mem++;
 
 
      *buf++ = hexchars[ch >> 4];
      *buf++ = hexchars[ch >> 4];
      *buf++ = hexchars[ch & 0xf];
      *buf++ = hexchars[ch & 0xf];
    }
    }
 
 
  *buf = 0;
  *buf = 0;
 
 
  return buf;
  return buf;
}
}
 
 
int
int
get_traceframe_number ()
get_traceframe_number ()
{
{
  return traceframe_number;
  return traceframe_number;
}
}
 
 
 
 
/* module initialization */
/* module initialization */
void
void
_initialize_tracepoint ()
_initialize_tracepoint ()
{
{
  tracepoint_chain = 0;
  tracepoint_chain = 0;
  tracepoint_count = 0;
  tracepoint_count = 0;
  traceframe_number = -1;
  traceframe_number = -1;
  tracepoint_number = -1;
  tracepoint_number = -1;
 
 
  set_internalvar (lookup_internalvar ("tpnum"),
  set_internalvar (lookup_internalvar ("tpnum"),
                   value_from_longest (builtin_type_int, (LONGEST) 0));
                   value_from_longest (builtin_type_int, (LONGEST) 0));
  set_internalvar (lookup_internalvar ("trace_frame"),
  set_internalvar (lookup_internalvar ("trace_frame"),
                   value_from_longest (builtin_type_int, (LONGEST) - 1));
                   value_from_longest (builtin_type_int, (LONGEST) - 1));
 
 
  if (tracepoint_list.list == NULL)
  if (tracepoint_list.list == NULL)
    {
    {
      tracepoint_list.listsize = 128;
      tracepoint_list.listsize = 128;
      tracepoint_list.list = xmalloc
      tracepoint_list.list = xmalloc
        (tracepoint_list.listsize * sizeof (struct memrange));
        (tracepoint_list.listsize * sizeof (struct memrange));
    }
    }
  if (tracepoint_list.aexpr_list == NULL)
  if (tracepoint_list.aexpr_list == NULL)
    {
    {
      tracepoint_list.aexpr_listsize = 128;
      tracepoint_list.aexpr_listsize = 128;
      tracepoint_list.aexpr_list = xmalloc
      tracepoint_list.aexpr_list = xmalloc
        (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *));
        (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *));
    }
    }
 
 
  if (stepping_list.list == NULL)
  if (stepping_list.list == NULL)
    {
    {
      stepping_list.listsize = 128;
      stepping_list.listsize = 128;
      stepping_list.list = xmalloc
      stepping_list.list = xmalloc
        (stepping_list.listsize * sizeof (struct memrange));
        (stepping_list.listsize * sizeof (struct memrange));
    }
    }
 
 
  if (stepping_list.aexpr_list == NULL)
  if (stepping_list.aexpr_list == NULL)
    {
    {
      stepping_list.aexpr_listsize = 128;
      stepping_list.aexpr_listsize = 128;
      stepping_list.aexpr_list = xmalloc
      stepping_list.aexpr_list = xmalloc
        (stepping_list.aexpr_listsize * sizeof (struct agent_expr *));
        (stepping_list.aexpr_listsize * sizeof (struct agent_expr *));
    }
    }
 
 
  add_info ("scope", scope_info,
  add_info ("scope", scope_info,
            "List the variables local to a scope");
            "List the variables local to a scope");
 
 
  add_cmd ("tracepoints", class_trace, NO_FUNCTION,
  add_cmd ("tracepoints", class_trace, NO_FUNCTION,
           "Tracing of program execution without stopping the program.",
           "Tracing of program execution without stopping the program.",
           &cmdlist);
           &cmdlist);
 
 
  add_info ("tracepoints", tracepoints_info,
  add_info ("tracepoints", tracepoints_info,
            "Status of tracepoints, or tracepoint number NUMBER.\n\
            "Status of tracepoints, or tracepoint number NUMBER.\n\
Convenience variable \"$tpnum\" contains the number of the\n\
Convenience variable \"$tpnum\" contains the number of the\n\
last tracepoint set.");
last tracepoint set.");
 
 
  add_info_alias ("tp", "tracepoints", 1);
  add_info_alias ("tp", "tracepoints", 1);
 
 
  add_com ("save-tracepoints", class_trace, tracepoint_save_command,
  add_com ("save-tracepoints", class_trace, tracepoint_save_command,
           "Save current tracepoint definitions as a script.\n\
           "Save current tracepoint definitions as a script.\n\
Use the 'source' command in another debug session to restore them.");
Use the 'source' command in another debug session to restore them.");
 
 
  add_com ("tdump", class_trace, trace_dump_command,
  add_com ("tdump", class_trace, trace_dump_command,
           "Print everything collected at the current tracepoint.");
           "Print everything collected at the current tracepoint.");
 
 
  add_prefix_cmd ("tfind", class_trace, trace_find_command,
  add_prefix_cmd ("tfind", class_trace, trace_find_command,
                  "Select a trace frame;\n\
                  "Select a trace frame;\n\
No argument means forward by one frame; '-' meand backward by one frame.",
No argument means forward by one frame; '-' meand backward by one frame.",
                  &tfindlist, "tfind ", 1, &cmdlist);
                  &tfindlist, "tfind ", 1, &cmdlist);
 
 
  add_cmd ("outside", class_trace, trace_find_outside_command,
  add_cmd ("outside", class_trace, trace_find_outside_command,
           "Select a trace frame whose PC is outside the given \
           "Select a trace frame whose PC is outside the given \
range.\nUsage: tfind outside addr1, addr2",
range.\nUsage: tfind outside addr1, addr2",
           &tfindlist);
           &tfindlist);
 
 
  add_cmd ("range", class_trace, trace_find_range_command,
  add_cmd ("range", class_trace, trace_find_range_command,
           "Select a trace frame whose PC is in the given range.\n\
           "Select a trace frame whose PC is in the given range.\n\
Usage: tfind range addr1,addr2",
Usage: tfind range addr1,addr2",
           &tfindlist);
           &tfindlist);
 
 
  add_cmd ("line", class_trace, trace_find_line_command,
  add_cmd ("line", class_trace, trace_find_line_command,
           "Select a trace frame by source line.\n\
           "Select a trace frame by source line.\n\
Argument can be a line number (with optional source file), \n\
Argument can be a line number (with optional source file), \n\
a function name, or '*' followed by an address.\n\
a function name, or '*' followed by an address.\n\
Default argument is 'the next source line that was traced'.",
Default argument is 'the next source line that was traced'.",
           &tfindlist);
           &tfindlist);
 
 
  add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
  add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
           "Select a trace frame by tracepoint number.\n\
           "Select a trace frame by tracepoint number.\n\
Default is the tracepoint for the current trace frame.",
Default is the tracepoint for the current trace frame.",
           &tfindlist);
           &tfindlist);
 
 
  add_cmd ("pc", class_trace, trace_find_pc_command,
  add_cmd ("pc", class_trace, trace_find_pc_command,
           "Select a trace frame by PC.\n\
           "Select a trace frame by PC.\n\
Default is the current PC, or the PC of the current trace frame.",
Default is the current PC, or the PC of the current trace frame.",
           &tfindlist);
           &tfindlist);
 
 
  add_cmd ("end", class_trace, trace_find_end_command,
  add_cmd ("end", class_trace, trace_find_end_command,
           "Synonym for 'none'.\n\
           "Synonym for 'none'.\n\
De-select any trace frame and resume 'live' debugging.",
De-select any trace frame and resume 'live' debugging.",
           &tfindlist);
           &tfindlist);
 
 
  add_cmd ("none", class_trace, trace_find_none_command,
  add_cmd ("none", class_trace, trace_find_none_command,
           "De-select any trace frame and resume 'live' debugging.",
           "De-select any trace frame and resume 'live' debugging.",
           &tfindlist);
           &tfindlist);
 
 
  add_cmd ("start", class_trace, trace_find_start_command,
  add_cmd ("start", class_trace, trace_find_start_command,
           "Select the first trace frame in the trace buffer.",
           "Select the first trace frame in the trace buffer.",
           &tfindlist);
           &tfindlist);
 
 
  add_com ("tstatus", class_trace, trace_status_command,
  add_com ("tstatus", class_trace, trace_status_command,
           "Display the status of the current trace data collection.");
           "Display the status of the current trace data collection.");
 
 
  add_com ("tstop", class_trace, trace_stop_command,
  add_com ("tstop", class_trace, trace_stop_command,
           "Stop trace data collection.");
           "Stop trace data collection.");
 
 
  add_com ("tstart", class_trace, trace_start_command,
  add_com ("tstart", class_trace, trace_start_command,
           "Start trace data collection.");
           "Start trace data collection.");
 
 
  add_com ("passcount", class_trace, trace_pass_command,
  add_com ("passcount", class_trace, trace_pass_command,
           "Set the passcount for a tracepoint.\n\
           "Set the passcount for a tracepoint.\n\
The trace will end when the tracepoint has been passed 'count' times.\n\
The trace will end when the tracepoint has been passed 'count' times.\n\
Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
if TPNUM is omitted, passcount refers to the last tracepoint defined.");
if TPNUM is omitted, passcount refers to the last tracepoint defined.");
 
 
  add_com ("end", class_trace, end_actions_pseudocommand,
  add_com ("end", class_trace, end_actions_pseudocommand,
           "Ends a list of commands or actions.\n\
           "Ends a list of commands or actions.\n\
Several GDB commands allow you to enter a list of commands or actions.\n\
Several GDB commands allow you to enter a list of commands or actions.\n\
Entering \"end\" on a line by itself is the normal way to terminate\n\
Entering \"end\" on a line by itself is the normal way to terminate\n\
such a list.\n\n\
such a list.\n\n\
Note: the \"end\" command cannot be used at the gdb prompt.");
Note: the \"end\" command cannot be used at the gdb prompt.");
 
 
  add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
  add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
           "Specify single-stepping behavior at a tracepoint.\n\
           "Specify single-stepping behavior at a tracepoint.\n\
Argument is number of instructions to trace in single-step mode\n\
Argument is number of instructions to trace in single-step mode\n\
following the tracepoint.  This command is normally followed by\n\
following the tracepoint.  This command is normally followed by\n\
one or more \"collect\" commands, to specify what to collect\n\
one or more \"collect\" commands, to specify what to collect\n\
while single-stepping.\n\n\
while single-stepping.\n\n\
Note: this command can only be used in a tracepoint \"actions\" list.");
Note: this command can only be used in a tracepoint \"actions\" list.");
 
 
  add_com_alias ("ws", "while-stepping", class_alias, 0);
  add_com_alias ("ws", "while-stepping", class_alias, 0);
  add_com_alias ("stepping", "while-stepping", class_alias, 0);
  add_com_alias ("stepping", "while-stepping", class_alias, 0);
 
 
  add_com ("collect", class_trace, collect_pseudocommand,
  add_com ("collect", class_trace, collect_pseudocommand,
           "Specify one or more data items to be collected at a tracepoint.\n\
           "Specify one or more data items to be collected at a tracepoint.\n\
Accepts a comma-separated list of (one or more) expressions.  GDB will\n\
Accepts a comma-separated list of (one or more) expressions.  GDB will\n\
collect all data (variables, registers) referenced by that expression.\n\
collect all data (variables, registers) referenced by that expression.\n\
Also accepts the following special arguments:\n\
Also accepts the following special arguments:\n\
    $regs   -- all registers.\n\
    $regs   -- all registers.\n\
    $args   -- all function arguments.\n\
    $args   -- all function arguments.\n\
    $locals -- all variables local to the block/function scope.\n\
    $locals -- all variables local to the block/function scope.\n\
Note: this command can only be used in a tracepoint \"actions\" list.");
Note: this command can only be used in a tracepoint \"actions\" list.");
 
 
  add_com ("actions", class_trace, trace_actions_command,
  add_com ("actions", class_trace, trace_actions_command,
           "Specify the actions to be taken at a tracepoint.\n\
           "Specify the actions to be taken at a tracepoint.\n\
Tracepoint actions may include collecting of specified data, \n\
Tracepoint actions may include collecting of specified data, \n\
single-stepping, or enabling/disabling other tracepoints, \n\
single-stepping, or enabling/disabling other tracepoints, \n\
depending on target's capabilities.");
depending on target's capabilities.");
 
 
  add_cmd ("tracepoints", class_trace, delete_trace_command,
  add_cmd ("tracepoints", class_trace, delete_trace_command,
           "Delete specified tracepoints.\n\
           "Delete specified tracepoints.\n\
Arguments are tracepoint numbers, separated by spaces.\n\
Arguments are tracepoint numbers, separated by spaces.\n\
No argument means delete all tracepoints.",
No argument means delete all tracepoints.",
           &deletelist);
           &deletelist);
 
 
  add_cmd ("tracepoints", class_trace, disable_trace_command,
  add_cmd ("tracepoints", class_trace, disable_trace_command,
           "Disable specified tracepoints.\n\
           "Disable specified tracepoints.\n\
Arguments are tracepoint numbers, separated by spaces.\n\
Arguments are tracepoint numbers, separated by spaces.\n\
No argument means disable all tracepoints.",
No argument means disable all tracepoints.",
           &disablelist);
           &disablelist);
 
 
  add_cmd ("tracepoints", class_trace, enable_trace_command,
  add_cmd ("tracepoints", class_trace, enable_trace_command,
           "Enable specified tracepoints.\n\
           "Enable specified tracepoints.\n\
Arguments are tracepoint numbers, separated by spaces.\n\
Arguments are tracepoint numbers, separated by spaces.\n\
No argument means enable all tracepoints.",
No argument means enable all tracepoints.",
           &enablelist);
           &enablelist);
 
 
  add_com ("trace", class_trace, trace_command,
  add_com ("trace", class_trace, trace_command,
           "Set a tracepoint at a specified line or function or address.\n\
           "Set a tracepoint at a specified line or function or address.\n\
Argument may be a line number, function name, or '*' plus an address.\n\
Argument may be a line number, function name, or '*' plus an address.\n\
For a line number or function, trace at the start of its code.\n\
For a line number or function, trace at the start of its code.\n\
If an address is specified, trace at that exact address.\n\n\
If an address is specified, trace at that exact address.\n\n\
Do \"help tracepoints\" for info on other tracepoint commands.");
Do \"help tracepoints\" for info on other tracepoint commands.");
 
 
  add_com_alias ("tp", "trace", class_alias, 0);
  add_com_alias ("tp", "trace", class_alias, 0);
  add_com_alias ("tr", "trace", class_alias, 1);
  add_com_alias ("tr", "trace", class_alias, 1);
  add_com_alias ("tra", "trace", class_alias, 1);
  add_com_alias ("tra", "trace", class_alias, 1);
  add_com_alias ("trac", "trace", class_alias, 1);
  add_com_alias ("trac", "trace", class_alias, 1);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.