2a9e7dbf384101675432c8b74558677277020d19
[external/binutils.git] / gdb / tracepoint.c
1 /* Tracing functionality for remote targets in custom GDB protocol
2    Copyright 1997 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #include "defs.h"
21 #include "symtab.h"
22 #include "frame.h"
23 #include "tracepoint.h"
24 #include "gdbtypes.h"
25 #include "expression.h"
26 #include "gdbcmd.h"
27 #include "value.h"
28 #include "target.h"
29 #include "language.h"
30 #include "gdb_string.h"
31
32 #include "ax.h"
33 #include "ax-gdb.h"
34
35 /* readline include files */
36 #include "readline.h"
37 #include "history.h"
38
39 /* readline defines this.  */
40 #undef savestring
41
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45
46 /* maximum length of an agent aexpression.
47    this accounts for the fact that packets are limited to 400 bytes
48    (which includes everything -- including the checksum), and assumes
49    the worst case of maximum length for each of the pieces of a
50    continuation packet.
51    
52    NOTE: expressions get mem2hex'ed otherwise this would be twice as
53    large.  (400 - 31)/2 == 184 */
54 #define MAX_AGENT_EXPR_LEN      184
55
56
57 extern int info_verbose;
58 extern void (*readline_begin_hook) PARAMS ((char *, ...));
59 extern char * (*readline_hook) PARAMS ((char *));
60 extern void (*readline_end_hook) PARAMS ((void));
61 extern void x_command PARAMS ((char *, int));
62 extern int addressprint;                /* Print machine addresses? */
63
64 /* If this definition isn't overridden by the header files, assume
65    that isatty and fileno exist on this system.  */
66 #ifndef ISATTY
67 #define ISATTY(FP)      (isatty (fileno (FP)))
68 #endif
69
70 /* 
71    Tracepoint.c:
72
73    This module defines the following debugger commands:
74    trace            : set a tracepoint on a function, line, or address.
75    info trace       : list all debugger-defined tracepoints.
76    delete trace     : delete one or more tracepoints.
77    enable trace     : enable one or more tracepoints.
78    disable trace    : disable one or more tracepoints.
79    actions          : specify actions to be taken at a tracepoint.
80    passcount        : specify a pass count for a tracepoint.
81    tstart           : start a trace experiment.
82    tstop            : stop a trace experiment.
83    tstatus          : query the status of a trace experiment.
84    tfind            : find a trace frame in the trace buffer.
85    tdump            : print everything collected at the current tracepoint.
86    save-tracepoints : write tracepoint setup into a file.
87
88    This module defines the following user-visible debugger variables:
89    $trace_frame : sequence number of trace frame currently being debugged.
90    $trace_line  : source line of trace frame currently being debugged.
91    $trace_file  : source file of trace frame currently being debugged.
92    $tracepoint  : tracepoint number of trace frame currently being debugged.
93    */
94
95
96 /* ======= Important global variables: ======= */
97
98 /* Chain of all tracepoints defined.  */
99 struct tracepoint *tracepoint_chain;
100
101 /* Number of last tracepoint made.  */
102 static int tracepoint_count;
103
104 /* Number of last traceframe collected.  */
105 static int traceframe_number;
106
107 /* Tracepoint for last traceframe collected.  */
108 static int tracepoint_number;
109
110 /* Symbol for function for last traceframe collected */
111 static struct symbol *traceframe_fun;
112
113 /* Symtab and line for last traceframe collected */
114 static struct symtab_and_line traceframe_sal;
115
116 /* Tracing command lists */
117 static struct cmd_list_element *tfindlist;
118
119 /* ======= Important command functions: ======= */
120 static void trace_command                 PARAMS ((char *, int));
121 static void tracepoints_info              PARAMS ((char *, int));
122 static void delete_trace_command          PARAMS ((char *, int));
123 static void enable_trace_command          PARAMS ((char *, int));
124 static void disable_trace_command         PARAMS ((char *, int));
125 static void trace_pass_command            PARAMS ((char *, int));
126 static void trace_actions_command         PARAMS ((char *, int));
127 static void trace_start_command           PARAMS ((char *, int));
128 static void trace_stop_command            PARAMS ((char *, int));
129 static void trace_status_command          PARAMS ((char *, int));
130 static void trace_find_command            PARAMS ((char *, int));
131 static void trace_find_pc_command         PARAMS ((char *, int));
132 static void trace_find_tracepoint_command PARAMS ((char *, int));
133 static void trace_find_line_command       PARAMS ((char *, int));
134 static void trace_find_range_command      PARAMS ((char *, int));
135 static void trace_find_outside_command    PARAMS ((char *, int));
136 static void tracepoint_save_command       PARAMS ((char *, int));
137 static void trace_dump_command            PARAMS ((char *, int));
138
139 /* support routines */
140 static void trace_mention                 PARAMS ((struct tracepoint *));
141
142 struct collection_list;
143 static void add_aexpr PARAMS ((struct collection_list *, struct agent_expr *));
144 static unsigned char *mem2hex(unsigned char *, unsigned char *, int);
145
146 /* Utility: returns true if "target remote" */
147 static int
148 target_is_remote ()
149 {
150   if (current_target.to_shortname &&
151       strcmp (current_target.to_shortname, "remote") == 0)
152     return 1;
153   else
154     return 0;
155 }
156
157 /* Utility: generate error from an incoming stub packet.  */
158 static void 
159 trace_error (buf)
160      char *buf;
161 {
162   if (*buf++ != 'E')
163     return;                     /* not an error msg */
164   switch (*buf) 
165     {
166     case '1':                   /* malformed packet error */
167       if (*++buf == '0')        /*   general case: */
168         error ("tracepoint.c: error in outgoing packet.");
169       else
170         error ("tracepoint.c: error in outgoing packet at field #%d.", 
171                strtol (buf, NULL, 16));
172     case '2':
173       error ("trace API error 0x%s.", ++buf);
174     default:
175       error ("Target returns error code '%s'.", buf);
176     }
177 }
178
179 /* Utility: wait for reply from stub, while accepting "O" packets */
180 static char *
181 remote_get_noisy_reply (buf)
182      char *buf;
183 {
184   do    /* loop on reply from remote stub */
185     {
186       QUIT;                             /* allow user to bail out with ^C */
187       getpkt (buf, 0);
188       if (buf[0] == 0)
189         error ("Target does not support this command.");
190       else if (buf[0] == 'E')
191         trace_error (buf);
192       else if (buf[0] == 'O' &&
193                buf[1] != 'K')
194         remote_console_output (buf + 1);        /* 'O' message from stub */
195       else
196         return buf;                             /* here's the actual reply */
197     } while (1);
198 }
199
200 /* Set tracepoint count to NUM.  */
201 static void
202 set_tracepoint_count (num)
203      int num;
204 {
205   tracepoint_count = num;
206   set_internalvar (lookup_internalvar ("tpnum"),
207                    value_from_longest (builtin_type_int, (LONGEST) num));
208 }
209
210 /* Set traceframe number to NUM.  */
211 static void
212 set_traceframe_num (num)
213      int num;
214 {
215   traceframe_number = num;
216   set_internalvar (lookup_internalvar ("trace_frame"),
217                    value_from_longest (builtin_type_int, (LONGEST) num));
218 }
219
220 /* Set tracepoint number to NUM.  */
221 static void
222 set_tracepoint_num (num)
223      int num;
224 {
225   tracepoint_number = num;
226   set_internalvar (lookup_internalvar ("tracepoint"),
227                    value_from_longest (builtin_type_int, (LONGEST) num));
228 }
229
230 /* Set externally visible debug variables for querying/printing
231    the traceframe context (line, function, file) */
232
233 static void
234 set_traceframe_context (trace_pc)
235      CORE_ADDR trace_pc;
236 {
237   static struct type *func_string, *file_string;
238   static struct type *func_range,  *file_range;
239   static value_ptr    func_val,     file_val;
240   static struct type *charstar;
241   int len;
242
243   if (charstar == (struct type *) NULL)
244     charstar = lookup_pointer_type (builtin_type_char);
245
246   if (trace_pc == -1)   /* cease debugging any trace buffers */
247     {
248       traceframe_fun = 0;
249       traceframe_sal.pc = traceframe_sal.line = 0;
250       traceframe_sal.symtab = NULL;
251       set_internalvar (lookup_internalvar ("trace_func"), 
252                        value_from_longest (charstar, (LONGEST) 0));
253       set_internalvar (lookup_internalvar ("trace_file"), 
254                        value_from_longest (charstar, (LONGEST) 0));
255       set_internalvar (lookup_internalvar ("trace_line"),
256                        value_from_longest (builtin_type_int, (LONGEST) -1));
257       return;
258     }
259
260   /* save as globals for internal use */
261   traceframe_sal = find_pc_line (trace_pc, 0);
262   traceframe_fun = find_pc_function (trace_pc);
263
264   /* save linenumber as "$trace_line", a debugger variable visible to users */
265   set_internalvar (lookup_internalvar ("trace_line"),
266                    value_from_longest (builtin_type_int, 
267                                        (LONGEST) traceframe_sal.line));
268
269   /* save func name as "$trace_func", a debugger variable visible to users */
270   if (traceframe_fun == NULL || 
271       SYMBOL_NAME (traceframe_fun) == NULL)
272     set_internalvar (lookup_internalvar ("trace_func"), 
273                      value_from_longest (charstar, (LONGEST) 0));
274   else
275     {
276       len = strlen (SYMBOL_NAME (traceframe_fun));
277       func_range  = create_range_type (func_range,  
278                                        builtin_type_int, 0, len - 1);
279       func_string = create_array_type (func_string, 
280                                        builtin_type_char, func_range);
281       func_val = allocate_value (func_string);
282       VALUE_TYPE (func_val) = func_string;
283       memcpy (VALUE_CONTENTS_RAW (func_val), 
284               SYMBOL_NAME (traceframe_fun), 
285               len);
286       func_val->modifiable = 0;
287       set_internalvar (lookup_internalvar ("trace_func"), func_val);
288     }
289
290   /* save file name as "$trace_file", a debugger variable visible to users */
291   if (traceframe_sal.symtab == NULL || 
292       traceframe_sal.symtab->filename == NULL)
293     set_internalvar (lookup_internalvar ("trace_file"), 
294                      value_from_longest (charstar, (LONGEST) 0));
295   else
296     {
297       len = strlen (traceframe_sal.symtab->filename);
298       file_range  = create_range_type (file_range,  
299                                        builtin_type_int, 0, len - 1);
300       file_string = create_array_type (file_string, 
301                                        builtin_type_char, file_range);
302       file_val = allocate_value (file_string);
303       VALUE_TYPE (file_val) = file_string;
304       memcpy (VALUE_CONTENTS_RAW (file_val), 
305               traceframe_sal.symtab->filename, 
306               len);
307       file_val->modifiable = 0;
308       set_internalvar (lookup_internalvar ("trace_file"), file_val);
309     }
310 }
311
312 /* Low level routine to set a tracepoint.
313    Returns the tracepoint object so caller can set other things.
314    Does not set the tracepoint number!
315    Does not print anything.
316
317    ==> This routine should not be called if there is a chance of later
318    error(); otherwise it leaves a bogus tracepoint on the chain.  Validate
319    your arguments BEFORE calling this routine!  */
320
321 static struct tracepoint *
322 set_raw_tracepoint (sal)
323      struct symtab_and_line sal;
324 {
325   register struct tracepoint *t, *tc;
326   struct cleanup *old_chain;
327
328   t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
329   old_chain = make_cleanup (free, t);
330   memset (t, 0, sizeof (*t));
331   t->address = sal.pc;
332   if (sal.symtab == NULL)
333     t->source_file = NULL;
334   else
335     {
336       if (sal.symtab->dirname == NULL)
337         {
338           t->source_file = (char *) xmalloc (strlen (sal.symtab->filename) + 1);
339           strcpy (t->source_file, sal.symtab->filename);
340         }
341       else
342         {
343           char *p;
344
345           t->source_file = (char *) xmalloc (strlen (sal.symtab->filename) +
346                                              strlen (sal.symtab->dirname) + 2);
347           
348           strcpy (t->source_file, sal.symtab->dirname);
349           p = t->source_file;
350           while (*p)
351             p++;
352           if (*(--p) != '/')            /* Will this work on Windows? */
353             strcat (t->source_file, "/");
354           strcat (t->source_file, sal.symtab->filename);
355         }
356     }
357
358   t->language = current_language->la_language;
359   t->input_radix = input_radix;
360   t->line_number = sal.line;
361   t->enabled     = enabled;
362   t->next        = 0;
363   t->step_count  = 0;
364   t->pass_count  = 0;
365   t->addr_string = NULL;
366
367   /* Add this tracepoint to the end of the chain
368      so that a list of tracepoints will come out in order
369      of increasing numbers.  */
370
371   tc = tracepoint_chain;
372   if (tc == 0)
373     tracepoint_chain = t;
374   else
375     {
376       while (tc->next)
377         tc = tc->next;
378       tc->next = t;
379     }
380   discard_cleanups (old_chain);
381   return t;
382 }
383
384 /* Set a tracepoint according to ARG (function, linenum or *address) */
385 static void
386 trace_command (arg, from_tty)
387      char *arg;
388      int from_tty;
389 {
390   char **canonical = (char **)NULL;
391   struct symtabs_and_lines sals;
392   struct symtab_and_line sal;
393   struct tracepoint *t;
394   char *addr_start = 0, *addr_end = 0;
395   int i;
396
397   if (!arg || !*arg)
398     error ("trace command requires an argument");
399
400   if (from_tty && info_verbose)
401     printf_filtered ("TRACE %s\n", arg);
402
403   addr_start = arg;
404   sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical);
405   addr_end   = arg;
406   if (! sals.nelts) 
407     return;     /* ??? Presumably decode_line_1 has already warned? */
408
409   /* Resolve all line numbers to PC's */
410   for (i = 0; i < sals.nelts; i++)
411     resolve_sal_pc (&sals.sals[i]);
412
413   /* Now set all the tracepoints.  */
414   for (i = 0; i < sals.nelts; i++)
415     {
416       sal = sals.sals[i];
417
418       t = set_raw_tracepoint (sal);
419       set_tracepoint_count (tracepoint_count + 1);
420       t->number = tracepoint_count;
421
422       /* If a canonical line spec is needed use that instead of the
423          command string.  */
424       if (canonical != (char **)NULL && canonical[i] != NULL)
425         t->addr_string = canonical[i];
426       else if (addr_start)
427         t->addr_string = savestring (addr_start, addr_end - addr_start);
428
429       trace_mention (t);
430
431       /* Let the UI know of any additions */
432       if (create_tracepoint_hook)
433         create_tracepoint_hook (t);
434     }
435
436   if (sals.nelts > 1)
437     {
438       printf_filtered ("Multiple tracepoints were set.\n");
439       printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
440     }
441 }
442
443 /* Tell the user we have just set a tracepoint TP. */
444
445 static void
446 trace_mention (tp)
447      struct tracepoint *tp;
448 {
449   printf_filtered ("Tracepoint %d", tp->number);
450
451   if (addressprint || (tp->source_file == NULL))
452     {
453       printf_filtered (" at ");
454       print_address_numeric (tp->address, 1, gdb_stdout);
455     }
456   if (tp->source_file)
457     printf_filtered (": file %s, line %d.",
458                      tp->source_file, tp->line_number);
459
460   printf_filtered ("\n");
461 }
462
463 /* Print information on tracepoint number TPNUM_EXP, or all if omitted.  */
464
465 static void
466 tracepoints_info (tpnum_exp, from_tty)
467      char *tpnum_exp;
468      int from_tty;
469 {
470   struct tracepoint *t;
471   struct action_line *action;
472   int found_a_tracepoint = 0;
473   char wrap_indent[80];
474   struct symbol *sym;
475   int tpnum = -1;
476
477   if (tpnum_exp)
478     tpnum = parse_and_eval_address (tpnum_exp);
479
480   ALL_TRACEPOINTS (t)
481     if (tpnum == -1 || tpnum == t->number)
482       {
483         extern int addressprint;        /* print machine addresses? */
484
485         if (!found_a_tracepoint++)
486           {
487             printf_filtered ("Num Enb ");
488             if (addressprint)
489               printf_filtered ("Address    ");
490             printf_filtered ("PassC StepC What\n");
491           }
492         strcpy (wrap_indent, "                           ");
493         if (addressprint)
494           strcat (wrap_indent, "           ");
495
496         printf_filtered ("%-3d %-3s ", t->number, 
497                          t->enabled == enabled ? "y" : "n");
498         if (addressprint)
499           printf_filtered ("%s ", 
500                            local_hex_string_custom ((unsigned long) t->address,
501                                                     "08l"));
502         printf_filtered ("%-5d %-5d ", t->pass_count, t->step_count);
503
504         if (t->source_file)
505           {
506             sym = find_pc_function (t->address);
507             if (sym)
508               {
509                 fputs_filtered ("in ", gdb_stdout);
510                 fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
511                 wrap_here (wrap_indent);
512                 fputs_filtered (" at ", gdb_stdout);
513               }
514             fputs_filtered (t->source_file, gdb_stdout);
515             printf_filtered (":%d", t->line_number);
516           }
517         else
518           print_address_symbolic (t->address, gdb_stdout, demangle, " ");
519
520         printf_filtered ("\n");
521         if (t->actions)
522           {
523             printf_filtered ("  Actions for tracepoint %d: \n", t->number);
524             for (action = t->actions; action; action = action->next)
525               {
526                 printf_filtered ("\t%s\n", action->action);
527               }
528           }
529       }
530   if (!found_a_tracepoint)
531     {
532       if (tpnum == -1)
533         printf_filtered ("No tracepoints.\n");
534       else
535         printf_filtered ("No tracepoint number %d.\n", tpnum);
536     }
537 }
538
539 /* Optimization: the code to parse an enable, disable, or delete TP command
540    is virtually identical except for whether it performs an enable, disable,
541    or delete.  Therefore I've combined them into one function with an opcode.
542    */
543 enum tracepoint_opcode 
544 {
545   enable, 
546   disable,
547   delete
548 };
549
550 /* This function implements enable, disable and delete. */
551 static void
552 tracepoint_operation (t, from_tty, opcode)
553      struct tracepoint *t;
554      int from_tty;
555      enum tracepoint_opcode opcode;
556 {
557   struct tracepoint *t2;
558
559   switch (opcode) {
560   case enable:
561     t->enabled = enabled;
562     if (modify_tracepoint_hook)
563       modify_tracepoint_hook (t);
564     break;
565   case disable:
566     t->enabled = disabled;
567     if (modify_tracepoint_hook)
568       modify_tracepoint_hook (t);
569     break;
570   case delete:
571     if (tracepoint_chain == t)
572       tracepoint_chain = t->next;
573
574     ALL_TRACEPOINTS (t2)
575       if (t2->next == t)
576         {
577           t2->next = t->next;
578           break;
579         }
580
581     /* Let the UI know of any deletions */
582     if (delete_tracepoint_hook)
583       delete_tracepoint_hook (t);
584
585     if (t->addr_string)
586       free (t->addr_string);
587     if (t->source_file)
588       free (t->source_file);
589     if (t->actions)
590       free_actions (t);
591
592     free (t);
593     break;
594   }
595 }
596
597 /* Utility: parse a tracepoint number and look it up in the list.  */
598 struct tracepoint *
599 get_tracepoint_by_number (arg)
600      char **arg;
601 {
602   struct tracepoint *t;
603   char *end, *copy;
604   value_ptr val;
605   int tpnum;
606
607   if (arg == 0)
608     error ("Bad tracepoint argument");
609
610   if (*arg == 0 || **arg == 0)  /* empty arg means refer to last tp */
611     tpnum = tracepoint_count;
612   else if (**arg == '$')        /* handle convenience variable */
613     {
614       /* Make a copy of the name, so we can null-terminate it
615          to pass to lookup_internalvar().  */
616       end = *arg + 1;
617       while (isalnum(*end) || *end == '_')
618         end++;
619       copy = (char *) alloca (end - *arg);
620       strncpy (copy, *arg + 1, (end - *arg - 1));
621       copy[end - *arg - 1] = '\0';
622       *arg = end;
623
624       val = value_of_internalvar (lookup_internalvar (copy));
625       if (TYPE_CODE( VALUE_TYPE (val)) != TYPE_CODE_INT)
626         error ("Convenience variable must have integral type.");
627       tpnum = (int) value_as_long (val);
628     }
629   else          /* handle tracepoint number */
630     {
631       tpnum = strtol (*arg, arg, 0);
632       if (tpnum == 0)           /* possible strtol failure */
633         while (**arg && !isspace (**arg))
634           (*arg)++;             /* advance to next white space, if any */
635     }
636   ALL_TRACEPOINTS (t)
637     if (t->number == tpnum)
638       {
639         return t;
640       }
641   printf_unfiltered ("No tracepoint number %d.\n", tpnum);
642   return NULL;
643 }
644
645 /* Utility: parse a list of tracepoint numbers, and call a func for each. */
646 static void
647 map_args_over_tracepoints (args, from_tty, opcode)
648      char *args;
649      int from_tty;
650      enum tracepoint_opcode opcode;
651 {
652   struct tracepoint *t, *tmp;
653   int tpnum;
654   char *cp;
655
656   if (args == 0 || *args == 0)  /* do them all */
657     ALL_TRACEPOINTS_SAFE (t, tmp)
658       tracepoint_operation (t, from_tty, opcode);
659   else
660     while (*args)
661       {
662         QUIT;           /* give user option to bail out with ^C */
663         if (t = get_tracepoint_by_number (&args))
664           tracepoint_operation (t, from_tty, opcode);
665         while (*args == ' ' || *args == '\t')
666           args++;
667       }
668 }
669
670 /* The 'enable trace' command enables tracepoints.  Not supported by all targets.  */
671 static void
672 enable_trace_command (args, from_tty)
673      char *args;
674      int from_tty;
675 {
676   dont_repeat ();
677   map_args_over_tracepoints (args, from_tty, enable);
678 }
679
680 /* The 'disable trace' command enables tracepoints.  Not supported by all targets.  */
681 static void
682 disable_trace_command (args, from_tty)
683      char *args;
684      int from_tty;
685 {
686   dont_repeat ();
687   map_args_over_tracepoints (args, from_tty, disable);
688 }
689
690 /* Remove a tracepoint (or all if no argument) */
691 static void
692 delete_trace_command (args, from_tty)
693      char *args;
694      int from_tty;
695 {
696   dont_repeat ();
697   if (!args || !*args)          /* No args implies all tracepoints; */
698     if (from_tty)               /* confirm only if from_tty... */
699       if (tracepoint_chain)     /* and if there are tracepoints to delete! */
700         if (!query ("Delete all tracepoints? "))
701           return;
702
703   map_args_over_tracepoints (args, from_tty, delete);
704 }
705
706 /* Set passcount for tracepoint.
707
708    First command argument is passcount, second is tracepoint number.
709    If tracepoint number omitted, apply to most recently defined.
710    Also accepts special argument "all".  */
711
712 static void
713 trace_pass_command (args, from_tty)
714      char *args;
715      int from_tty;
716 {
717   struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
718   unsigned long count;
719
720   if (args == 0 || *args == 0)
721     error ("PASS command requires an argument (count + optional TP num)");
722
723   count = strtoul (args, &args, 10);    /* count comes first, then TP num */
724
725   while (*args && isspace (*args))
726     args++;
727
728   if (*args && strncasecmp (args, "all", 3) == 0)
729     args += 3;  /* skip special argument "all" */
730   else
731     t1 = get_tracepoint_by_number (&args);
732
733   if (*args)
734     error ("Junk at end of arguments.");
735
736   if (t1 == NULL)
737     return;     /* error, bad tracepoint number */
738
739   ALL_TRACEPOINTS (t2)
740     if (t1 == (struct tracepoint *) -1 || t1 == t2)
741       {
742         t2->pass_count = count;
743         if (modify_tracepoint_hook)
744           modify_tracepoint_hook (t2);
745         if (from_tty)
746           printf_filtered ("Setting tracepoint %d's passcount to %d\n", 
747                            t2->number, count);
748       }
749 }
750
751 /* ACTIONS functions: */
752
753 /* Prototypes for action-parsing utility commands  */
754 static void  read_actions PARAMS((struct tracepoint *));
755 static char *parse_and_eval_memrange PARAMS ((char *,
756                                               CORE_ADDR, 
757                                               long *,
758                                               bfd_signed_vma *,
759                                               long *));
760
761 /* The three functions:
762         collect_pseudocommand, 
763         while_stepping_pseudocommand, and 
764         end_actions_pseudocommand
765    are placeholders for "commands" that are actually ONLY to be used
766    within a tracepoint action list.  If the actual function is ever called,
767    it means that somebody issued the "command" at the top level,
768    which is always an error.  */
769
770 static void 
771 end_actions_pseudocommand (args, from_tty)
772      char *args;
773      int from_tty;
774 {
775   error ("This command cannot be used at the top level.");
776 }
777
778 static void
779 while_stepping_pseudocommand (args, from_tty)
780      char *args;
781      int from_tty;
782 {
783   error ("This command can only be used in a tracepoint actions list.");
784 }
785
786 static void
787 collect_pseudocommand (args, from_tty)
788      char *args;
789      int from_tty;
790 {
791   error ("This command can only be used in a tracepoint actions list.");
792 }
793
794 /* Enter a list of actions for a tracepoint.  */
795 static void
796 trace_actions_command (args, from_tty)
797      char *args;
798      int from_tty;
799 {
800   struct tracepoint *t;
801   char *actions;
802   char tmpbuf[128];
803   char *end_msg = "End with a line saying just \"end\".";
804
805   if (t = get_tracepoint_by_number (&args))
806     {
807       sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
808                t->number);
809
810       if (from_tty)
811         {
812           if (readline_begin_hook)
813             (*readline_begin_hook) ("%s  %s\n", tmpbuf, end_msg);
814           else if (input_from_terminal_p ())
815             printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
816         }
817
818       free_actions (t);
819       t->step_count = 0;        /* read_actions may set this */
820       read_actions (t);
821
822       if (readline_end_hook)
823         (*readline_end_hook) ();
824
825       /* tracepoints_changed () */
826     }
827   /* else error, just return; */
828 }
829
830 /* worker function */
831 static void
832 read_actions (t)
833      struct tracepoint *t;
834 {
835   char *line;
836   char *prompt1 = "> ", *prompt2 = "  > ";
837   char *prompt = prompt1;
838   enum actionline_type linetype;
839   extern FILE *instream;
840   struct action_line *next = NULL, *temp;
841   struct cleanup *old_chain;
842
843   /* Control-C quits instantly if typed while in this loop
844      since it should not wait until the user types a newline.  */
845   immediate_quit++;
846 #ifdef STOP_SIGNAL
847   if (job_control)
848     signal (STOP_SIGNAL, stop_sig);
849 #endif
850   old_chain = make_cleanup (free_actions, (void *) t);
851   while (1)
852     {
853       /* Make sure that all output has been output.  Some machines may let
854          you get away with leaving out some of the gdb_flush, but not all.  */
855       wrap_here ("");
856       gdb_flush (gdb_stdout);
857       gdb_flush (gdb_stderr);
858
859       if (readline_hook && instream == NULL)
860         line = (*readline_hook) (prompt);
861       else if (instream == stdin && ISATTY (instream))
862         {
863           line = readline (prompt);
864           if (line && *line)            /* add it to command history */
865             add_history (line);
866         }
867       else
868         line = gdb_readline (0);
869
870       linetype = validate_actionline (&line, t);
871       if (linetype == BADLINE)
872         continue;       /* already warned -- collect another line */
873
874       temp = xmalloc (sizeof (struct action_line));
875       temp->next = NULL;
876       temp->action = line;
877
878       if (next == NULL)         /* first action for this tracepoint? */
879         t->actions = next = temp;
880       else
881         {
882           next->next = temp;
883           next = temp;
884         }
885
886       if (linetype == STEPPING) /* begin "while-stepping" */
887         if (prompt == prompt2)
888           {
889             warning ("Already processing 'while-stepping'");
890             continue;
891           }
892         else
893           prompt = prompt2;     /* change prompt for stepping actions */
894       else if (linetype == END)
895         if (prompt == prompt2)
896           {
897             prompt = prompt1;   /* end of single-stepping actions */
898           }
899         else
900           { /* end of actions */
901             if (t->actions->next == NULL)
902               {
903                 /* an "end" all by itself with no other actions means
904                    this tracepoint has no actions.  Discard empty list. */
905                 free_actions (t);
906               }
907             break;
908           }
909     }
910 #ifdef STOP_SIGNAL
911   if (job_control)
912     signal (STOP_SIGNAL, SIG_DFL);
913 #endif
914   immediate_quit = 0;
915   discard_cleanups (old_chain);
916 }
917
918 /* worker function */
919 enum actionline_type
920 validate_actionline (line, t)
921      char **line;
922      struct tracepoint *t;
923 {
924   struct cmd_list_element *c;
925   struct expression *exp = NULL;
926   value_ptr temp, temp2;
927   struct cleanup *old_chain = NULL;
928   char *p;
929
930   for (p = *line; isspace (*p); )
931     p++;
932
933   /* symbol lookup etc. */
934   if (*p == '\0')       /* empty line: just prompt for another line. */
935     return BADLINE;
936
937   if (*p == '#')        /* comment line */
938     return GENERIC;
939
940   c = lookup_cmd (&p, cmdlist, "", -1, 1);
941   if (c == 0)
942     {
943       warning ("'%s' is not an action that I know, or is ambiguous.", p);
944       return BADLINE;
945     }
946     
947   if (c->function.cfunc == collect_pseudocommand)
948     {
949       struct agent_expr *aexpr;
950       struct agent_reqs areqs;
951
952       do {                      /* repeat over a comma-separated list */
953         QUIT;                   /* allow user to bail out with ^C */
954         while (isspace (*p))
955           p++;
956
957         if (*p == '$')                  /* look for special pseudo-symbols */
958           {
959             long typecode, size;
960             bfd_signed_vma offset;
961
962             if ((0 == strncasecmp ("reg", p + 1, 3)) ||
963                 (0 == strncasecmp ("arg", p + 1, 3)) ||
964                 (0 == strncasecmp ("loc", p + 1, 3)))
965               {
966                 p = strchr (p, ',');
967                 continue;
968               }
969             /* else fall thru, treat p as an expression and parse it! */
970           }
971         exp   = parse_exp_1 (&p, block_for_pc (t->address), 1);
972         old_chain = make_cleanup (free_current_contents, &exp);
973
974         if (exp->elts[0].opcode == OP_VAR_VALUE)
975           if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
976             {
977               warning ("%s is constant (value %d): will not be collected.",
978                        SYMBOL_NAME (exp->elts[2].symbol),
979                        SYMBOL_VALUE (exp->elts[2].symbol));
980               return BADLINE;
981             }
982           else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
983             {
984               warning ("%s is optimized away and cannot be collected.",
985                        SYMBOL_NAME (exp->elts[2].symbol));
986               return BADLINE;
987             }
988
989         /* we have something to collect, make sure that the expr to
990            bytecode translator can handle it and that it's not too long */
991         aexpr = gen_trace_for_expr(exp);
992         (void) make_cleanup (free_agent_expr, aexpr);
993
994         if (aexpr->len > MAX_AGENT_EXPR_LEN)
995           error ("expression too complicated, try simplifying");
996
997         ax_reqs(aexpr, &areqs);
998         (void) make_cleanup (free, areqs.reg_mask);
999
1000         if (areqs.flaw != agent_flaw_none)
1001           error ("malformed expression");
1002
1003         if (areqs.min_height < 0)
1004           error ("gdb: Internal error: expression has min height < 0");
1005
1006         if (areqs.max_height > 20)
1007           error ("expression too complicated, try simplifying");
1008
1009         do_cleanups (old_chain);
1010       } while (p && *p++ == ',');
1011       return GENERIC;
1012     }
1013   else if (c->function.cfunc == while_stepping_pseudocommand)
1014     {
1015       char *steparg;    /* in case warning is necessary */
1016
1017       while (isspace (*p))
1018         p++;
1019       steparg = p;
1020
1021       if (*p == '\0' ||
1022           (t->step_count = strtol (p, &p, 0)) == 0)
1023         {
1024           warning ("bad step-count: command ignored.", *line);
1025           return BADLINE;
1026         }
1027       return STEPPING;
1028     }
1029   else if (c->function.cfunc == end_actions_pseudocommand)
1030     return END;
1031   else
1032     {
1033       warning ("'%s' is not a supported tracepoint action.", *line);
1034       return BADLINE;
1035     }
1036 }
1037
1038 /* worker function */
1039 void 
1040 free_actions (t)
1041      struct tracepoint *t;
1042 {
1043   struct action_line *line, *next;
1044
1045   for (line = t->actions; line; line = next)
1046     {
1047       next = line->next;
1048       if (line->action) 
1049         free (line->action);
1050       free (line);
1051     }
1052   t->actions = NULL;
1053 }
1054
1055 struct memrange {
1056   int type;             /* 0 for absolute memory range, else basereg number */
1057   bfd_signed_vma start;
1058   bfd_signed_vma end;
1059 };
1060
1061 struct collection_list {
1062   unsigned char regs_mask[8];   /* room for up to 256 regs */
1063   long listsize;
1064   long next_memrange;
1065   struct memrange *list;
1066   long aexpr_listsize;          /* size of array pointed to by expr_list elt */
1067   long next_aexpr_elt;
1068   struct agent_expr **aexpr_list;
1069   
1070 } tracepoint_list, stepping_list;
1071
1072 /* MEMRANGE functions: */
1073
1074 static int memrange_cmp PARAMS ((const void *, const void *));
1075
1076 /* compare memranges for qsort */
1077 static int
1078 memrange_cmp (va, vb)
1079      const void *va;
1080      const void *vb;
1081 {
1082   const struct memrange *a = va, *b = vb;
1083
1084   if (a->type < b->type)
1085     return -1;
1086   if (a->type > b->type)
1087     return  1;
1088   if (a->type == 0)
1089     {
1090       if ((bfd_vma) a->start  < (bfd_vma) b->start)  return -1;
1091       if ((bfd_vma) a->start  > (bfd_vma) b->start)  return  1;
1092     }
1093   else
1094     {
1095       if (a->start  < b->start)
1096         return -1;
1097       if (a->start  > b->start)
1098         return  1;
1099     }
1100   return 0;
1101 }
1102
1103 /* Sort the memrange list using qsort, and merge adjacent memranges */
1104 static void
1105 memrange_sortmerge (memranges)
1106      struct collection_list *memranges;
1107 {
1108   int a, b;
1109
1110   qsort (memranges->list, memranges->next_memrange, 
1111          sizeof (struct memrange), memrange_cmp);
1112   if (memranges->next_memrange > 0)
1113     {
1114       for (a = 0, b = 1; b < memranges->next_memrange; b++)
1115         {
1116           if (memranges->list[a].type == memranges->list[b].type &&
1117               memranges->list[b].start - memranges->list[a].end <= 
1118               MAX_REGISTER_VIRTUAL_SIZE)
1119             {
1120               /* memrange b starts before memrange a ends; merge them.  */
1121               if (memranges->list[b].end > memranges->list[a].end)
1122                 memranges->list[a].end = memranges->list[b].end;
1123               continue;         /* next b, same a */
1124             }
1125           a++;                  /* next a */
1126           if (a != b)
1127             memcpy (&memranges->list[a], &memranges->list[b], 
1128                     sizeof (struct memrange));
1129         }
1130       memranges->next_memrange = a + 1;
1131     }
1132 }
1133
1134 /* Add a register to a collection list */
1135 void
1136 add_register (collection, regno)
1137      struct collection_list *collection;
1138      unsigned long regno;
1139 {
1140   if (info_verbose)
1141     printf_filtered ("collect register %d\n", regno);
1142   if (regno > (8 * sizeof (collection->regs_mask)))
1143     error ("Internal: register number %d too large for tracepoint",
1144            regno);
1145   collection->regs_mask [regno / 8] |= 1 << (regno  % 8);
1146 }
1147
1148 /* Add a memrange to a collection list */
1149 static void
1150 add_memrange (memranges, type, base, len)
1151      struct collection_list *memranges;
1152      int type;
1153      bfd_signed_vma base;
1154      unsigned long len;
1155 {
1156   if (info_verbose)
1157     printf_filtered ("(%d,0x%x,%d)\n", type, base, len);
1158   /* type: 0 == memory, n == basereg */
1159   memranges->list[memranges->next_memrange].type  = type;
1160   /* base: addr if memory, offset if reg relative. */
1161   memranges->list[memranges->next_memrange].start = base;
1162   /* len: we actually save end (base + len) for convenience */
1163   memranges->list[memranges->next_memrange].end   = base + len;
1164   memranges->next_memrange++;
1165   if (memranges->next_memrange >= memranges->listsize)
1166     {
1167       memranges->listsize *= 2;
1168       memranges->list = xrealloc (memranges->list, 
1169                                   memranges->listsize);
1170     }
1171
1172   if (type != -1)       /* better collect the base register! */
1173     add_register (memranges, type);
1174 }
1175
1176 /* Add a symbol to a collection list */
1177 static void
1178 collect_symbol (collect, sym)
1179      struct collection_list *collect;
1180      struct symbol *sym;
1181 {
1182   unsigned long  len;
1183   unsigned long  reg;
1184   bfd_signed_vma offset;
1185
1186   len  = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
1187   switch (SYMBOL_CLASS (sym)) {
1188   default:
1189     printf_filtered ("%s: don't know symbol class %d\n",
1190                      SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
1191     break;
1192   case LOC_CONST:
1193     printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1194                      SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
1195     break;
1196   case LOC_STATIC:
1197     offset = SYMBOL_VALUE_ADDRESS (sym); 
1198     if (info_verbose)
1199       printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
1200                        SYMBOL_NAME (sym), len, offset);
1201     add_memrange (collect, -1, offset, len);    /* 0 == memory */
1202     break;
1203   case LOC_REGISTER:
1204   case LOC_REGPARM:
1205     reg = SYMBOL_VALUE (sym); 
1206     if (info_verbose)
1207       printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
1208     add_register (collect, reg);
1209     /* check for doubles stored in two registers */
1210     /* FIXME: how about larger types stored in 3 or more regs? */
1211     if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
1212         len > REGISTER_RAW_SIZE (reg))
1213       add_register (collect, reg + 1);
1214     break;
1215   case LOC_REF_ARG:
1216     printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
1217     printf_filtered ("       (will not collect %s)\n", 
1218                      SYMBOL_NAME (sym));
1219     break;
1220   case LOC_ARG:
1221     offset = SYMBOL_VALUE (sym);
1222     reg = FP_REGNUM;
1223     if (info_verbose)
1224       {
1225         printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1226                          SYMBOL_NAME (sym), len);
1227         printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
1228       }
1229     add_memrange (collect, reg, offset, len);
1230     break;
1231   case LOC_REGPARM_ADDR:
1232     reg = SYMBOL_VALUE (sym);
1233     offset = 0;
1234     if (info_verbose)
1235       {
1236         printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset",
1237                          SYMBOL_NAME (sym), len);
1238         printf_filtered (" %d from reg %d\n", offset, reg);
1239       }
1240     add_memrange (collect, reg, offset, len);
1241     break;
1242   case LOC_LOCAL:
1243   case LOC_LOCAL_ARG:
1244     offset = SYMBOL_VALUE (sym);
1245     reg = FP_REGNUM;
1246     if (info_verbose)
1247       {
1248         printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1249                          SYMBOL_NAME (sym), len);
1250         printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
1251       }
1252     add_memrange (collect, reg, offset, len);
1253     break;
1254   case LOC_BASEREG:
1255   case LOC_BASEREG_ARG:
1256     reg = SYMBOL_BASEREG (sym);
1257     offset  = SYMBOL_VALUE (sym);
1258     if (info_verbose)
1259       {
1260         printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n", 
1261                          SYMBOL_NAME (sym), len, offset, reg);
1262       }
1263     add_memrange (collect, reg, offset, len);
1264     break;
1265   case LOC_UNRESOLVED:
1266     printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
1267     break;
1268   case LOC_OPTIMIZED_OUT:
1269     printf_filtered ("%s has been optimized out of existance.\n",
1270                      SYMBOL_NAME (sym));
1271     break;
1272   }
1273 }
1274
1275 /* Add all locals (or args) symbols to collection list */
1276 static void
1277 add_local_symbols (collect, pc, type)
1278      struct collection_list *collect;
1279      CORE_ADDR pc;
1280      int type;
1281 {
1282   struct symbol *sym;
1283   struct block  *block;
1284   int i, nsyms, count = 0;
1285
1286   block = block_for_pc (pc);
1287   while (block != 0)
1288     {
1289       QUIT;                             /* allow user to bail out with ^C */
1290       nsyms = BLOCK_NSYMS (block);
1291       for (i = 0; i < nsyms; i++)
1292         {
1293           sym = BLOCK_SYM (block, i);
1294           switch (SYMBOL_CLASS (sym)) {
1295           case LOC_LOCAL:
1296           case LOC_STATIC:
1297           case LOC_REGISTER:
1298           case LOC_BASEREG:
1299             if (type == 'L')    /* collecting Locals */
1300               {
1301                 count++;
1302                 collect_symbol (collect, sym);
1303               }
1304             break;
1305           case LOC_ARG:
1306           case LOC_LOCAL_ARG:
1307           case LOC_REF_ARG:
1308           case LOC_REGPARM:
1309           case LOC_REGPARM_ADDR:
1310           case LOC_BASEREG_ARG:
1311             if (type == 'A')    /* collecting Arguments */
1312               {
1313                 count++;
1314                 collect_symbol (collect, sym);
1315               }
1316           }
1317         }
1318       if (BLOCK_FUNCTION (block))
1319         break;
1320       else
1321         block = BLOCK_SUPERBLOCK (block);
1322     }
1323   if (count == 0)
1324     warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
1325 }
1326
1327 /* worker function */
1328 static void
1329 clear_collection_list (list)
1330      struct collection_list *list;
1331 {
1332   int ndx;
1333
1334   list->next_memrange = 0;
1335   for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
1336     {
1337       free_agent_expr(list->aexpr_list[ndx]);
1338       list->aexpr_list[ndx] = NULL;
1339     }
1340   list->next_aexpr_elt = 0;
1341   memset (list->regs_mask, 0, sizeof (list->regs_mask));
1342 }
1343
1344 /* reduce a collection list to string form (for gdb protocol) */
1345 static char **
1346 stringify_collection_list (list, string)
1347      struct collection_list *list;
1348      char *string;
1349 {
1350   char temp_buf[2048];
1351   int count;
1352   int ndx = 0;
1353   char *(*str_list)[];
1354   char *end;
1355   long  i;
1356
1357   count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
1358   str_list = (char *(*)[])xmalloc(count * sizeof (char *));
1359
1360   for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1361     if (list->regs_mask[i] != 0)        /* skip leading zeroes in regs_mask */
1362       break;
1363   if (list->regs_mask[i] != 0)  /* prepare to send regs_mask to the stub */
1364     {
1365       if (info_verbose)
1366         printf_filtered ("\nCollecting registers (mask): 0x");
1367       end = temp_buf;
1368       *end++='R';
1369       for (; i >= 0; i--)
1370         {
1371           QUIT;                         /* allow user to bail out with ^C */
1372           if (info_verbose)
1373             printf_filtered ("%02X", list->regs_mask[i]);
1374           sprintf (end,  "%02X", list->regs_mask[i]);
1375           end += 2;
1376         }
1377       (*str_list)[ndx] = savestring(temp_buf, end - temp_buf);
1378       ndx++;
1379     }
1380   if (info_verbose)
1381     printf_filtered ("\n");
1382   if (list->next_memrange > 0 && info_verbose)
1383     printf_filtered ("Collecting memranges: \n");
1384   for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
1385     {
1386       QUIT;                     /* allow user to bail out with ^C */
1387       if (info_verbose)
1388         printf_filtered ("(%d, 0x%x, %d)\n", 
1389                          list->list[i].type, 
1390                          list->list[i].start, 
1391                          list->list[i].end - list->list[i].start);
1392       if (count + 27 > MAX_AGENT_EXPR_LEN)
1393         {
1394           (*str_list)[ndx] = savestring(temp_buf, count);
1395           ndx++;
1396           count = 0;
1397           end = temp_buf;
1398         }
1399       sprintf (end, "M%X,%X,%X", 
1400                list->list[i].type, 
1401                list->list[i].start, 
1402                list->list[i].end - list->list[i].start);
1403       count += strlen (end);
1404       end += strlen (end);
1405     }
1406
1407   for (i = 0; i < list->next_aexpr_elt; i++)
1408     {
1409       QUIT;                     /* allow user to bail out with ^C */
1410       if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
1411         {
1412           (*str_list)[ndx] = savestring(temp_buf, count);
1413           ndx++;
1414           count = 0;
1415           end = temp_buf;
1416         }
1417       sprintf (end, "X%08X,", list->aexpr_list[i]->len);
1418       end += 10;                /* 'X' + 8 hex digits + ',' */
1419       count += 10;
1420
1421       end = mem2hex(list->aexpr_list[i]->buf, end, list->aexpr_list[i]->len);
1422       count += 2 * list->aexpr_list[i]->len;
1423     }
1424
1425   if (count != 0)
1426     {
1427       (*str_list)[ndx] = savestring(temp_buf, count);
1428       ndx++;
1429       count = 0;
1430       end = temp_buf;
1431     }
1432   (*str_list)[ndx] = NULL;
1433
1434   if (ndx == 0)
1435     return NULL;
1436   else
1437     return *str_list;
1438 }
1439
1440 void
1441 free_actions_list(actions_list)
1442      char **actions_list;
1443 {
1444   int ndx;
1445
1446   if (actions_list == 0)
1447     return;
1448
1449   for (ndx = 0; actions_list[ndx]; ndx++)
1450     free(actions_list[ndx]);
1451
1452   free(actions_list);
1453 }
1454
1455 /* render all actions into gdb protocol */
1456 static void
1457 encode_actions (t, tdp_actions, stepping_actions)
1458      struct tracepoint  *t;
1459      char              ***tdp_actions;
1460      char              ***stepping_actions;
1461 {
1462   static char        tdp_buff[2048], step_buff[2048];
1463   char               *action_exp;
1464   struct expression  *exp = NULL;
1465   struct action_line *action;
1466   bfd_signed_vma      offset;
1467   long                i;
1468   value_ptr           tempval;
1469   struct collection_list  *collect;
1470   struct cmd_list_element *cmd;
1471   struct agent_expr *aexpr;
1472
1473   clear_collection_list (&tracepoint_list);
1474   clear_collection_list (&stepping_list);
1475   collect = &tracepoint_list;
1476
1477   *tdp_actions = NULL;
1478   *stepping_actions = NULL;
1479
1480   for (action = t->actions; action; action = action->next)
1481     {
1482       QUIT;                     /* allow user to bail out with ^C */
1483       action_exp = action->action;
1484       while (isspace (*action_exp))
1485         action_exp++;
1486
1487       if (*action_exp == '#')   /* comment line */
1488         return;
1489
1490       cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
1491       if (cmd == 0)
1492         error ("Bad action list item: %s", action_exp);
1493
1494       if (cmd->function.cfunc == collect_pseudocommand)
1495         {
1496           do {  /* repeat over a comma-separated list */
1497             QUIT;               /* allow user to bail out with ^C */
1498             while (isspace (*action_exp))
1499               action_exp++;
1500
1501             if (0 == strncasecmp ("$reg", action_exp, 4))
1502               {
1503                 for (i = 0; i < NUM_REGS; i++)
1504                   add_register (collect, i);
1505                 action_exp = strchr (action_exp, ','); /* more? */
1506               }
1507             else if (0 == strncasecmp ("$arg", action_exp, 4))
1508               {
1509                 add_local_symbols (collect, t->address, 'A');
1510                 action_exp = strchr (action_exp, ','); /* more? */
1511               }
1512             else if (0 == strncasecmp ("$loc", action_exp, 4))
1513               {
1514                 add_local_symbols (collect, t->address, 'L');
1515                 action_exp = strchr (action_exp, ','); /* more? */
1516               }
1517             else
1518               {
1519                 unsigned long addr, len;
1520                 struct cleanup *old_chain = NULL;
1521                 struct cleanup *old_chain1 = NULL;
1522                 struct agent_reqs areqs;
1523
1524                 exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
1525                 old_chain = make_cleanup (free_current_contents, &exp);
1526
1527                 switch (exp->elts[0].opcode) {
1528                 case OP_REGISTER:
1529                   i = exp->elts[1].longconst;
1530                   if (info_verbose)
1531                     printf_filtered ("OP_REGISTER: ");
1532                   add_register (collect, i);
1533                   break;
1534
1535                 case UNOP_MEMVAL:
1536                   /* safe because we know it's a simple expression */
1537                   tempval = evaluate_expression (exp);
1538                   addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
1539                   len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
1540                   add_memrange (collect, -1, addr, len);
1541                   break;
1542
1543                 case OP_VAR_VALUE:
1544                   collect_symbol (collect, exp->elts[2].symbol);
1545                   break;
1546
1547                 default:        /* full-fledged expression */
1548                   aexpr = gen_trace_for_expr (exp);
1549
1550                   old_chain1 = make_cleanup (free_agent_expr, aexpr);
1551
1552                   ax_reqs (aexpr, &areqs);
1553                   if (areqs.flaw != agent_flaw_none)
1554                     error ("malformed expression");
1555
1556                   if (areqs.min_height < 0)
1557                     error ("gdb: Internal error: expression has min height < 0");
1558                   if (areqs.max_height > 20)
1559                     error ("expression too complicated, try simplifying");
1560
1561                   discard_cleanups (old_chain1);
1562                   add_aexpr (collect, aexpr);
1563
1564                   /* take care of the registers */
1565                   if (areqs.reg_mask_len > 0)
1566                     {
1567                       int ndx1;
1568                       int ndx2;
1569
1570                       for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
1571                         {
1572                           QUIT;         /* allow user to bail out with ^C */
1573                           if (areqs.reg_mask[ndx1] != 0)
1574                             {
1575                               /* assume chars have 8 bits */
1576                               for (ndx2 = 0; ndx2 < 8; ndx2++)
1577                                 if (areqs.reg_mask[ndx1] & (1 << ndx2))
1578                                   /* it's used -- record it */
1579                                   add_register (collect, ndx1 * 8 + ndx2);
1580                             }
1581                         }
1582                     }
1583                   break;
1584                 }       /* switch */
1585                 do_cleanups (old_chain);
1586               }         /* do */
1587           } while (action_exp && *action_exp++ == ',');
1588         }               /* if */
1589       else if (cmd->function.cfunc == while_stepping_pseudocommand)
1590         {
1591           collect = &stepping_list;
1592         }
1593       else if (cmd->function.cfunc == end_actions_pseudocommand)
1594         {
1595           if (collect == &stepping_list)        /* end stepping actions */
1596             collect = &tracepoint_list;
1597           else
1598             break;                      /* end tracepoint actions */
1599         }
1600     }                   /* for */
1601   memrange_sortmerge (&tracepoint_list); 
1602   memrange_sortmerge (&stepping_list); 
1603
1604   *tdp_actions      = stringify_collection_list (&tracepoint_list, &tdp_buff);
1605   *stepping_actions = stringify_collection_list (&stepping_list,   &step_buff);
1606 }
1607
1608 static void
1609 add_aexpr(collect, aexpr)
1610      struct collection_list *collect;
1611      struct agent_expr *aexpr;
1612 {
1613   if (collect->next_aexpr_elt >= collect->aexpr_listsize)
1614     {
1615       collect->aexpr_list =
1616         xrealloc (collect->aexpr_list,
1617                   2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
1618       collect->aexpr_listsize *= 2;
1619     }
1620   collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
1621   collect->next_aexpr_elt++;
1622 }
1623
1624 static char target_buf[2048];
1625
1626 /* Set "transparent" memory ranges
1627
1628    Allow trace mechanism to treat text-like sections
1629    (and perhaps all read-only sections) transparently, 
1630    i.e. don't reject memory requests from these address ranges
1631    just because they haven't been collected.  */
1632
1633 static void
1634 remote_set_transparent_ranges (void)
1635 {
1636   extern bfd *exec_bfd;
1637   asection *s;
1638   bfd_size_type size;
1639   bfd_vma lma;
1640   int anysecs = 0;
1641
1642   if (!exec_bfd)
1643     return;             /* no information to give. */
1644
1645   strcpy (target_buf, "QTro");
1646   for (s = exec_bfd->sections; s; s = s->next)
1647     {
1648       char tmp[40];
1649
1650       if ((s->flags & SEC_LOAD)     == 0 ||
1651        /* (s->flags & SEC_CODE)     == 0 || */
1652           (s->flags & SEC_READONLY) == 0)
1653         continue;
1654
1655       anysecs = 1;
1656       lma  = s->lma;
1657       size = bfd_get_section_size_before_reloc (s);
1658       sprintf (tmp, ":%x,%x", lma, lma + size);
1659       strcat (target_buf, tmp);
1660     }
1661   if (anysecs)
1662     {
1663       putpkt (target_buf);
1664       getpkt (target_buf, 0);
1665     }
1666 }
1667
1668 /* tstart command:
1669  
1670    Tell target to clear any previous trace experiment.
1671    Walk the list of tracepoints, and send them (and their actions)
1672    to the target.  If no errors, 
1673    Tell target to start a new trace experiment.  */
1674
1675 static void
1676 trace_start_command (args, from_tty)
1677      char *args;
1678      int from_tty;
1679 { /* STUB_COMM MOSTLY_IMPLEMENTED */
1680   struct tracepoint *t;
1681   char buf[2048];
1682   char **tdp_actions;
1683   char **stepping_actions;
1684   int ndx;
1685   struct cleanup *old_chain = NULL;
1686
1687   dont_repeat ();       /* like "run", dangerous to repeat accidentally */
1688   
1689   if (target_is_remote ())
1690     {
1691       putpkt ("QTinit");
1692       remote_get_noisy_reply (target_buf);
1693       if (strcmp (target_buf, "OK"))
1694         error ("Target does not support this command.");
1695
1696       ALL_TRACEPOINTS (t)
1697         {
1698           int ss_count;         /* if actions include singlestepping */
1699           int disable_mask;     /* ??? */
1700           int enable_mask;      /* ??? */
1701
1702           sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address, 
1703                    t->enabled == enabled ? 'E' : 'D', 
1704                    t->step_count, t->pass_count);
1705
1706           if (t->actions)
1707             strcat (buf, "-");
1708           putpkt (buf);
1709           remote_get_noisy_reply (target_buf);
1710           if (strcmp (target_buf, "OK"))
1711             error ("Target does not support tracepoints.");
1712
1713           if (t->actions)
1714             {
1715               encode_actions (t, &tdp_actions, &stepping_actions);
1716               old_chain = make_cleanup (free_actions_list, tdp_actions);
1717               (void) make_cleanup (free_actions_list, stepping_actions);
1718
1719               /* do_single_steps (t); */
1720               if (tdp_actions)
1721                 {
1722                   for (ndx = 0; tdp_actions[ndx]; ndx++)
1723                     {
1724                       QUIT;             /* allow user to bail out with ^C */
1725                       sprintf (buf, "QTDP:-%x:%x:%s%c",
1726                                t->number, t->address,
1727                                tdp_actions[ndx],
1728                                ((tdp_actions[ndx+1] || stepping_actions)
1729                                 ? '-' : 0));
1730                       putpkt (buf);
1731                       remote_get_noisy_reply (target_buf);
1732                       if (strcmp (target_buf, "OK"))
1733                         error ("Error on target while setting tracepoints.");
1734                     }
1735                 }
1736               if (stepping_actions)
1737                 {
1738                   for (ndx = 0; stepping_actions[ndx]; ndx++)
1739                     {
1740                       QUIT;             /* allow user to bail out with ^C */
1741                       sprintf (buf, "QTDP:-%x:%x:%s%s%s",
1742                                t->number, t->address,
1743                                ((ndx == 0) ? "S" : ""),
1744                                stepping_actions[ndx],
1745                                (stepping_actions[ndx+1] ? "-" : ""));
1746                       putpkt (buf);
1747                       remote_get_noisy_reply (target_buf);
1748                       if (strcmp (target_buf, "OK"))
1749                         error ("Error on target while setting tracepoints.");
1750                     }
1751                 }
1752
1753               do_cleanups (old_chain);
1754             }
1755         }
1756       /* Tell target to treat text-like sections as transparent */
1757       remote_set_transparent_ranges ();
1758       /* Now insert traps and begin collecting data */
1759       putpkt ("QTStart");
1760       remote_get_noisy_reply (target_buf);
1761       if (strcmp (target_buf, "OK"))
1762         error ("Bogus reply from target: %s", target_buf);
1763       set_traceframe_num (-1);  /* all old traceframes invalidated */
1764       set_tracepoint_num (-1);
1765       set_traceframe_context(-1);
1766       trace_running_p = 1;
1767     }
1768   else
1769     error ("Trace can only be run on remote targets.");
1770 }
1771
1772 /* tstop command */
1773 static void
1774 trace_stop_command (args, from_tty)
1775      char *args;
1776      int from_tty;
1777 { /* STUB_COMM IS_IMPLEMENTED */
1778   if (target_is_remote ())
1779     {
1780       putpkt ("QTStop");
1781       remote_get_noisy_reply (target_buf);
1782       if (strcmp (target_buf, "OK"))
1783         error ("Bogus reply from target: %s", target_buf);
1784       trace_running_p = 0;
1785     }
1786   else
1787     error ("Trace can only be run on remote targets.");
1788 }
1789
1790 unsigned long trace_running_p;
1791
1792 /* tstatus command */
1793 static void
1794 trace_status_command (args, from_tty)
1795      char *args;
1796      int from_tty;
1797 { /* STUB_COMM IS_IMPLEMENTED */
1798   if (target_is_remote ())
1799     {
1800       putpkt ("qTStatus");
1801       remote_get_noisy_reply (target_buf);
1802
1803       if (target_buf[0] != 'T' ||
1804           (target_buf[1] != '0' && target_buf[1] != '1'))
1805         error ("Bogus reply from target: %s", target_buf);
1806
1807       /* exported for use by the GUI */
1808       trace_running_p = (target_buf[1] == '1');
1809     }
1810   else
1811     error ("Trace can only be run on remote targets.");
1812 }
1813
1814 /* Worker function for the various flavors of the tfind command */
1815 static void
1816 finish_tfind_command (msg, from_tty)
1817      char *msg;
1818      int from_tty;
1819 {
1820   int target_frameno = -1, target_tracept = -1;
1821   CORE_ADDR old_frame_addr;
1822   struct symbol *old_func;
1823   char *reply;
1824
1825   old_frame_addr = FRAME_FP (get_current_frame ());
1826   old_func       = find_pc_function (read_pc ());
1827
1828   putpkt (msg);
1829   reply = remote_get_noisy_reply (msg);
1830
1831   while (reply && *reply)
1832     switch (*reply) {
1833     case 'F':
1834       if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
1835         { 
1836           /* A request for a non-existant trace frame has failed.
1837              Our response will be different, depending on FROM_TTY:
1838
1839              If FROM_TTY is true, meaning that this command was 
1840              typed interactively by the user, then give an error
1841              and DO NOT change the state of traceframe_number etc.
1842
1843              However if FROM_TTY is false, meaning that we're either
1844              in a script, a loop, or a user-defined command, then 
1845              DON'T give an error, but DO change the state of
1846              traceframe_number etc. to invalid.
1847
1848              The rationalle is that if you typed the command, you
1849              might just have committed a typo or something, and you'd
1850              like to NOT lose your current debugging state.  However
1851              if you're in a user-defined command or especially in a
1852              loop, then you need a way to detect that the command
1853              failed WITHOUT aborting.  This allows you to write
1854              scripts that search thru the trace buffer until the end,
1855              and then continue on to do something else.  */
1856
1857           if (from_tty)
1858             error ("Target failed to find requested trace frame.");
1859           else
1860             {
1861               if (info_verbose)
1862                 printf_filtered ("End of trace buffer.\n");
1863               /* The following will not recurse, since it's special-cased */
1864               trace_find_command ("-1", from_tty);
1865               reply = NULL;     /* break out of loop, 
1866                                    (avoid recursive nonsense) */
1867             }
1868         }
1869       break;
1870     case 'T':
1871       if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
1872         error ("Target failed to find requested trace frame.");
1873       break;
1874     case 'O':   /* "OK"? */
1875       if (reply[1] == 'K' && reply[2] == '\0')
1876         reply += 2;
1877       else
1878         error ("Bogus reply from target: %s", reply);
1879       break;
1880     default:
1881       error ("Bogus reply from target: %s", reply);
1882     }
1883
1884   flush_cached_frames ();
1885   registers_changed ();
1886   select_frame (get_current_frame (), 0);
1887   set_traceframe_num (target_frameno);
1888   set_tracepoint_num (target_tracept);
1889   if (target_frameno == -1)
1890     set_traceframe_context (-1);
1891   else
1892     set_traceframe_context (read_pc ());
1893
1894   if (from_tty)
1895     {
1896       int source_only;
1897
1898       /* NOTE: in immitation of the step command, try to determine
1899          whether we have made a transition from one function to another.
1900          If so, we'll print the "stack frame" (ie. the new function and
1901          it's arguments) -- otherwise we'll just show the new source line.
1902
1903          This determination is made by checking (1) whether the current
1904          function has changed, and (2) whether the current FP has changed.
1905          Hack: if the FP wasn't collected, either at the current or the
1906          previous frame, assume that the FP has NOT changed.  */
1907
1908       if (old_func       == find_pc_function (read_pc ()) &&
1909          (old_frame_addr == 0 ||
1910           FRAME_FP (get_current_frame ()) == 0 ||
1911           old_frame_addr == FRAME_FP (get_current_frame ())))
1912         source_only = -1;
1913       else
1914         source_only =  1;
1915
1916       print_stack_frame (selected_frame, selected_frame_level, source_only);
1917       do_displays ();
1918     }
1919 }
1920
1921 /* trace_find_command takes a trace frame number n, 
1922    sends "QTFrame:<n>" to the target, 
1923    and accepts a reply that may contain several optional pieces
1924    of information: a frame number, a tracepoint number, and an
1925    indication of whether this is a trap frame or a stepping frame.
1926
1927    The minimal response is just "OK" (which indicates that the 
1928    target does not give us a frame number or a tracepoint number).
1929    Instead of that, the target may send us a string containing
1930    any combination of:
1931         F<hexnum>       (gives the selected frame number)
1932         T<hexnum>       (gives the selected tracepoint number)
1933    */
1934
1935 /* tfind command */
1936 static void
1937 trace_find_command (args, from_tty)
1938      char *args;
1939      int from_tty;
1940 { /* STUB_COMM PART_IMPLEMENTED */
1941   /* this should only be called with a numeric argument */
1942   int frameno = -1;
1943   char *tmp;
1944
1945   if (target_is_remote ())
1946     {
1947       if (args == 0 || *args == 0)
1948         { /* TFIND with no args means find NEXT trace frame. */
1949           if (traceframe_number == -1)
1950             frameno = 0;        /* "next" is first one */
1951           else
1952             frameno = traceframe_number + 1;
1953         }
1954       else if (0 == strcmp (args, "-"))
1955         {
1956           if (traceframe_number == -1)
1957             error ("not debugging trace buffer");
1958           else if (from_tty && traceframe_number == 0)
1959             error ("already at start of trace buffer");
1960
1961           frameno = traceframe_number - 1;
1962         }
1963       else
1964         frameno = parse_and_eval_address (args);
1965
1966       if (frameno < -1)
1967         error ("invalid input (%d is less than zero)", frameno);
1968
1969       sprintf (target_buf, "QTFrame:%x", frameno);
1970       finish_tfind_command (target_buf, from_tty);
1971     }
1972   else
1973     error ("Trace can only be run on remote targets.");
1974 }
1975
1976 /* tfind end */
1977 static void
1978 trace_find_end_command (args, from_tty)
1979      char *args;
1980      int from_tty;
1981 {
1982   trace_find_command ("-1", from_tty);
1983 }
1984
1985 /* tfind none */
1986 static void
1987 trace_find_none_command (args, from_tty)
1988      char *args;
1989      int from_tty;
1990 {
1991   trace_find_command ("-1", from_tty);
1992 }
1993
1994 /* tfind start */
1995 static void
1996 trace_find_start_command (args, from_tty)
1997      char *args;
1998      int from_tty;
1999 {
2000   trace_find_command ("0", from_tty);
2001 }
2002
2003 /* tfind pc command */
2004 static void
2005 trace_find_pc_command (args, from_tty)
2006      char *args;
2007      int from_tty;
2008 { /* STUB_COMM PART_IMPLEMENTED */
2009   CORE_ADDR pc;
2010   char *tmp;
2011
2012   if (target_is_remote ())
2013     {
2014       if (args == 0 || *args == 0)
2015         pc = read_pc ();        /* default is current pc */
2016       else
2017         pc = parse_and_eval_address (args);
2018
2019       sprintf (target_buf, "QTFrame:pc:%x", pc);
2020       finish_tfind_command (target_buf, from_tty);
2021     }
2022   else
2023     error ("Trace can only be run on remote targets.");
2024 }
2025
2026 /* tfind tracepoint command */
2027 static void
2028 trace_find_tracepoint_command (args, from_tty)
2029      char *args;
2030      int from_tty;
2031 { /* STUB_COMM PART_IMPLEMENTED */
2032   int tdp;
2033   char buf[40], *tmp;
2034
2035   if (target_is_remote ())
2036     {
2037       if (args == 0 || *args == 0)
2038         if (tracepoint_number == -1)
2039           error ("No current tracepoint -- please supply an argument.");
2040         else
2041           tdp = tracepoint_number;      /* default is current TDP */
2042       else
2043         tdp = parse_and_eval_address (args);
2044
2045       sprintf (target_buf, "QTFrame:tdp:%x", tdp);
2046       finish_tfind_command (target_buf, from_tty);
2047     }
2048   else
2049     error ("Trace can only be run on remote targets.");
2050 }
2051
2052 /* TFIND LINE command:
2053  
2054    This command will take a sourceline for argument, just like BREAK
2055    or TRACE (ie. anything that "decode_line_1" can handle).  
2056    
2057    With no argument, this command will find the next trace frame 
2058    corresponding to a source line OTHER THAN THE CURRENT ONE.  */
2059
2060 static void
2061 trace_find_line_command (args, from_tty)
2062      char *args;
2063      int from_tty;
2064 { /* STUB_COMM PART_IMPLEMENTED */
2065   static CORE_ADDR start_pc, end_pc;
2066   struct symtabs_and_lines sals;
2067   struct symtab_and_line sal;
2068   char *tmp;
2069   struct cleanup *old_chain;
2070
2071   if (target_is_remote ())
2072     {
2073       if (args == 0 || *args == 0)
2074         {
2075           sal = find_pc_line ((get_current_frame ())->pc, 0);
2076           sals.nelts = 1;
2077           sals.sals = (struct symtab_and_line *)
2078             xmalloc (sizeof (struct symtab_and_line));
2079           sals.sals[0] = sal;
2080         }
2081       else
2082         {
2083           sals = decode_line_spec (args, 1);
2084           sal  = sals.sals[0];
2085         }
2086
2087       old_chain = make_cleanup (free, sals.sals);
2088       if (sal.symtab == 0)
2089         {
2090           printf_filtered ("TFIND: No line number information available");
2091           if (sal.pc != 0)
2092             {
2093               /* This is useful for "info line *0x7f34".  If we can't tell the
2094                  user about a source line, at least let them have the symbolic
2095                  address.  */
2096               printf_filtered (" for address ");
2097               wrap_here ("  ");
2098               print_address (sal.pc, gdb_stdout);
2099               printf_filtered (";\n -- will attempt to find by PC. \n");
2100             }
2101           else
2102             {
2103               printf_filtered (".\n");
2104               return;   /* no line, no PC; what can we do? */
2105             }
2106         }
2107       else if (sal.line > 0
2108                && find_line_pc_range (sal, &start_pc, &end_pc))
2109         {
2110           if (start_pc == end_pc)
2111             {
2112               printf_filtered ("Line %d of \"%s\"",
2113                                sal.line, sal.symtab->filename);
2114               wrap_here ("  ");
2115               printf_filtered (" is at address ");
2116               print_address (start_pc, gdb_stdout);
2117               wrap_here ("  ");
2118               printf_filtered (" but contains no code.\n");
2119               sal = find_pc_line (start_pc, 0);
2120               if (sal.line > 0 &&
2121                   find_line_pc_range (sal, &start_pc, &end_pc) &&
2122                   start_pc != end_pc)
2123                 printf_filtered ("Attempting to find line %d instead.\n",
2124                                  sal.line);
2125               else
2126                 error ("Cannot find a good line.");
2127             }
2128         }
2129       else
2130         /* Is there any case in which we get here, and have an address
2131            which the user would want to see?  If we have debugging symbols
2132            and no line numbers?  */
2133         error ("Line number %d is out of range for \"%s\".\n",
2134                sal.line, sal.symtab->filename);
2135
2136       if (args && *args)        /* find within range of stated line */
2137         sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
2138       else                      /* find OUTSIDE OF range of CURRENT line */
2139         sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
2140       finish_tfind_command (target_buf, from_tty);
2141       do_cleanups (old_chain);
2142     }
2143   else
2144       error ("Trace can only be run on remote targets.");
2145 }
2146
2147 /* tfind range command */
2148 static void
2149 trace_find_range_command (args, from_tty)
2150      char *args;
2151      int from_tty;
2152 { /* STUB_COMM PART_IMPLEMENTED */
2153   static CORE_ADDR start, stop;
2154   char *tmp;
2155
2156   if (target_is_remote ())
2157     {
2158       if (args == 0 || *args == 0)
2159         { /* XXX FIXME: what should default behavior be? */
2160           printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
2161           return;
2162         }
2163
2164       if (0 != (tmp = strchr (args, ',' )))
2165         {
2166           *tmp++ = '\0';        /* terminate start address */
2167           while (isspace (*tmp))
2168             tmp++;
2169           start = parse_and_eval_address (args);
2170           stop  = parse_and_eval_address (tmp);
2171         }
2172       else
2173         { /* no explicit end address? */
2174           start = parse_and_eval_address (args);
2175           stop  = start + 1; /* ??? */
2176         }
2177
2178       sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
2179       finish_tfind_command (target_buf, from_tty);
2180     }
2181   else
2182       error ("Trace can only be run on remote targets.");
2183 }
2184
2185 /* tfind outside command */
2186 static void
2187 trace_find_outside_command (args, from_tty)
2188      char *args;
2189      int from_tty;
2190 { /* STUB_COMM PART_IMPLEMENTED */
2191   CORE_ADDR start, stop;
2192   char *tmp;
2193
2194   if (target_is_remote ())
2195     {
2196       if (args == 0 || *args == 0)
2197         { /* XXX FIXME: what should default behavior be? */
2198           printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
2199           return;
2200         }
2201
2202       if (0 != (tmp = strchr (args, ',' )))
2203         {
2204           *tmp++ = '\0';        /* terminate start address */
2205           while (isspace (*tmp))
2206             tmp++;
2207           start = parse_and_eval_address (args);
2208           stop  = parse_and_eval_address (tmp);
2209         }
2210       else
2211         { /* no explicit end address? */
2212           start = parse_and_eval_address (args);
2213           stop  = start + 1; /* ??? */
2214         }
2215
2216       sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
2217       finish_tfind_command (target_buf, from_tty);
2218     }
2219   else
2220       error ("Trace can only be run on remote targets.");
2221 }
2222
2223 /* save-tracepoints command */
2224 static void
2225 tracepoint_save_command (args, from_tty)
2226      char *args;
2227      int from_tty;
2228 {
2229   struct tracepoint  *tp;
2230   struct action_line *line;
2231   FILE *fp;
2232   char *i1 = "    ", *i2 = "      ";
2233   char *indent, *actionline;
2234
2235   if (args == 0 || *args == 0)
2236     error ("Argument required (file name in which to save tracepoints");
2237
2238   if (tracepoint_chain == 0)
2239     {
2240       warning ("save-tracepoints: no tracepoints to save.\n");
2241       return;
2242     }
2243
2244   if (!(fp = fopen (args, "w")))
2245     error ("Unable to open file '%s' for saving tracepoints");
2246
2247   ALL_TRACEPOINTS (tp)
2248     {
2249       if (tp->addr_string)
2250         fprintf (fp, "trace %s\n", tp->addr_string);
2251       else
2252         fprintf (fp, "trace *0x%x\n", tp->address);
2253
2254       if (tp->pass_count)
2255         fprintf (fp, "  passcount %d\n", tp->pass_count);
2256
2257       if (tp->actions)
2258         {
2259           fprintf (fp, "  actions\n");
2260           indent = i1;
2261           for (line = tp->actions; line; line = line->next)
2262             {
2263               struct cmd_list_element *cmd;
2264
2265               QUIT;                     /* allow user to bail out with ^C */
2266               actionline = line->action;
2267               while (isspace(*actionline))
2268                 actionline++;
2269
2270               fprintf (fp, "%s%s\n", indent, actionline);
2271               if (*actionline != '#')   /* skip for comment lines */
2272                 {
2273                   cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
2274                   if (cmd == 0)
2275                     error ("Bad action list item: %s", actionline);
2276                   if (cmd->function.cfunc == while_stepping_pseudocommand)
2277                     indent = i2;
2278                   else if (cmd->function.cfunc == end_actions_pseudocommand)
2279                     indent = i1;
2280                 }
2281             }
2282         }
2283     }
2284   fclose (fp);
2285   if (from_tty)
2286     printf_filtered ("Tracepoints saved to file '%s'.\n", args);
2287   return;
2288 }
2289
2290 /* info scope command: list the locals for a scope.  */
2291 static void
2292 scope_info (args, from_tty)
2293      char *args;
2294      int from_tty;
2295 {
2296   struct symtab_and_line sal;
2297   struct symtabs_and_lines sals;
2298   struct symbol *sym;
2299   struct minimal_symbol *msym;
2300   struct block *block;
2301   char **canonical, *symname, *save_args = args;
2302   int i, nsyms, count = 0;
2303
2304   if (args == 0 || *args == 0)
2305     error ("requires an argument (function, line or *addr) to define a scope");
2306
2307   sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2308   if (sals.nelts == 0)
2309     return;             /* presumably decode_line_1 has already warned */
2310
2311   /* Resolve line numbers to PC */
2312   resolve_sal_pc (&sals.sals[0]);
2313   block = block_for_pc (sals.sals[0].pc);
2314
2315   while (block != 0)
2316     {
2317       QUIT;                             /* allow user to bail out with ^C */
2318       nsyms = BLOCK_NSYMS (block);
2319       for (i = 0; i < nsyms; i++)
2320         {
2321           QUIT;                         /* allow user to bail out with ^C */
2322           if (count == 0)
2323             printf_filtered ("Scope for %s:\n", save_args);
2324           count++;
2325           sym = BLOCK_SYM (block, i);
2326           symname = SYMBOL_NAME (sym);
2327           if (symname == NULL || *symname == '\0')
2328             continue;   /* probably botched, certainly useless */
2329
2330           printf_filtered ("Symbol %s is ", symname);
2331           switch (SYMBOL_CLASS (sym)) {
2332           default:
2333           case LOC_UNDEF:               /* messed up symbol? */
2334             printf_filtered ("a bogus symbol, class %d.\n", 
2335                              SYMBOL_CLASS (sym));
2336             count--;                    /* don't count this one */
2337             continue;
2338           case LOC_CONST:
2339             printf_filtered ("a constant with value %d (0x%x)", 
2340                              SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
2341             break;
2342           case LOC_CONST_BYTES:
2343             printf_filtered ("constant bytes: ");
2344             if (SYMBOL_TYPE (sym))
2345               for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (sym)); i++)
2346                 fprintf_filtered (gdb_stdout, " %02x",
2347                                   (unsigned) SYMBOL_VALUE_BYTES (sym) [i]);
2348             break;
2349           case LOC_STATIC:
2350             printf_filtered ("in static storage at address ");
2351             print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2352             break;
2353           case LOC_REGISTER:
2354             printf_filtered ("a local variable in register $%s",
2355                              reg_names [SYMBOL_VALUE (sym)]);
2356             break;
2357           case LOC_ARG:
2358           case LOC_LOCAL_ARG:
2359             printf_filtered ("an argument at stack/frame offset %ld",
2360                              SYMBOL_VALUE (sym));
2361             break;
2362           case LOC_LOCAL:
2363             printf_filtered ("a local variable at frame offset %ld",
2364                              SYMBOL_VALUE (sym));
2365             break;
2366           case LOC_REF_ARG:
2367             printf_filtered ("a reference argument at offset %ld",
2368                              SYMBOL_VALUE (sym));
2369             break;
2370           case LOC_REGPARM:
2371             printf_filtered ("an argument in register $%s",
2372                              reg_names[SYMBOL_VALUE (sym)]);
2373             break;
2374           case LOC_REGPARM_ADDR:
2375             printf_filtered ("the address of an argument, in register $%s",
2376                              reg_names[SYMBOL_VALUE (sym)]);
2377             break;
2378           case LOC_TYPEDEF:
2379             printf_filtered ("a typedef.\n");
2380             continue;
2381           case LOC_LABEL:
2382             printf_filtered ("a label at address ");
2383             print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2384             break;
2385           case LOC_BLOCK:
2386             printf_filtered ("a function at address ");
2387             print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
2388                                    gdb_stdout);
2389             break;
2390           case LOC_BASEREG:
2391             printf_filtered ("a variable at offset %d from register $%s",
2392                              SYMBOL_VALUE (sym),
2393                              reg_names [SYMBOL_BASEREG (sym)]);
2394             break;
2395           case LOC_BASEREG_ARG:
2396             printf_filtered ("an argument at offset %d from register $%s",
2397                              SYMBOL_VALUE (sym),
2398                              reg_names [SYMBOL_BASEREG (sym)]);
2399             break;
2400           case LOC_UNRESOLVED:
2401             msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
2402             if (msym == NULL)
2403               printf_filtered ("Unresolved Static");
2404             else
2405               {
2406                 printf_filtered ("static storage at address ");
2407                 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1, 
2408                                        gdb_stdout);
2409               }
2410             break;
2411           case LOC_OPTIMIZED_OUT:
2412             printf_filtered ("optimized out.\n");
2413             continue;
2414           }
2415           if (SYMBOL_TYPE (sym))
2416             printf_filtered (", length %d.\n", 
2417                              TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
2418         }
2419       if (BLOCK_FUNCTION (block))
2420         break;
2421       else
2422         block = BLOCK_SUPERBLOCK (block);
2423     }
2424   if (count <= 0)
2425     printf_filtered ("Scope for %s contains no locals or arguments.\n",
2426                      save_args);
2427 }
2428
2429 /* worker function (cleanup) */
2430 static void
2431 replace_comma (comma)
2432      char *comma;
2433 {
2434   *comma = ',';
2435 }
2436
2437 /* tdump command */
2438 static void
2439 trace_dump_command (args, from_tty)
2440      char *args;
2441      int from_tty;
2442 {
2443   struct tracepoint  *t;
2444   struct action_line *action;
2445   char               *action_exp, *next_comma;
2446   struct cleanup     *old_cleanups;
2447   int                 stepping_actions = 0;
2448   int                 stepping_frame   = 0;
2449
2450   if (!target_is_remote ())
2451     {
2452       error ("Trace can only be run on remote targets.");
2453       return;
2454     }
2455
2456   if (tracepoint_number == -1)
2457     {
2458       warning ("No current trace frame.");
2459       return;
2460     }
2461
2462   ALL_TRACEPOINTS (t)
2463     if (t->number == tracepoint_number)
2464       break;
2465
2466   if (t == NULL)
2467     error ("No known tracepoint matches 'current' tracepoint #%d.", 
2468            tracepoint_number);
2469
2470   old_cleanups = make_cleanup (null_cleanup, NULL);
2471
2472   printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n", 
2473                    tracepoint_number, traceframe_number);
2474
2475   /* The current frame is a trap frame if the frame PC is equal
2476      to the tracepoint PC.  If not, then the current frame was
2477      collected during single-stepping.  */
2478
2479   stepping_frame = (t->address != read_pc());
2480
2481   for (action = t->actions; action; action = action->next)
2482     {
2483       struct cmd_list_element *cmd;
2484
2485       QUIT;                             /* allow user to bail out with ^C */
2486       action_exp = action->action;
2487       while (isspace (*action_exp))
2488         action_exp++;
2489
2490       /* The collection actions to be done while stepping are
2491          bracketed by the commands "while-stepping" and "end".  */
2492
2493       if (*action_exp == '#')   /* comment line */
2494         continue;
2495
2496       cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
2497       if (cmd == 0)
2498         error ("Bad action list item: %s", action_exp);
2499
2500       if (cmd->function.cfunc == while_stepping_pseudocommand)
2501         stepping_actions = 1;
2502       else if (cmd->function.cfunc == end_actions_pseudocommand)
2503         stepping_actions = 0;
2504       else if (cmd->function.cfunc == collect_pseudocommand)
2505         {
2506           /* Display the collected data.
2507              For the trap frame, display only what was collected at the trap.
2508              Likewise for stepping frames, display only what was collected
2509              while stepping.  This means that the two boolean variables,
2510              STEPPING_FRAME and STEPPING_ACTIONS should be equal.  */
2511           if (stepping_frame == stepping_actions)
2512             {
2513               do { /* repeat over a comma-separated list */
2514                 QUIT;           /* allow user to bail out with ^C */
2515                 if (*action_exp == ',')
2516                   action_exp++;
2517                 while (isspace (*action_exp))
2518                   action_exp++;
2519
2520                 next_comma = strchr (action_exp, ',');
2521
2522                 if      (0 == strncasecmp (action_exp, "$reg", 4))
2523                   registers_info (NULL, from_tty);
2524                 else if (0 == strncasecmp (action_exp, "$loc", 4))
2525                   locals_info (NULL, from_tty);
2526                 else if (0 == strncasecmp (action_exp, "$arg", 4))
2527                   args_info (NULL, from_tty);
2528                 else
2529                   { /* variable */
2530                     if (next_comma)
2531                       {
2532                         make_cleanup (replace_comma, next_comma);
2533                         *next_comma = '\0';
2534                       }
2535                     printf_filtered ("%s = ", action_exp);
2536                     output_command (action_exp, from_tty);
2537                     printf_filtered ("\n");
2538                   }
2539                 if (next_comma)
2540                   *next_comma = ',';
2541                 action_exp = next_comma;
2542               } while (action_exp && *action_exp == ',');
2543             }
2544         }
2545     }
2546   discard_cleanups (old_cleanups);
2547 }
2548
2549 /* Convert the memory pointed to by mem into hex, placing result in buf.
2550  * Return a pointer to the last char put in buf (null)
2551  * "stolen" from sparc-stub.c
2552  */
2553
2554 static const char hexchars[]="0123456789abcdef";
2555
2556 static unsigned char *
2557 mem2hex(mem, buf, count)
2558      unsigned char *mem;
2559      unsigned char *buf;
2560      int count;
2561 {
2562   unsigned char ch;
2563
2564   while (count-- > 0)
2565     {
2566       ch = *mem++;
2567
2568       *buf++ = hexchars[ch >> 4];
2569       *buf++ = hexchars[ch & 0xf];
2570     }
2571
2572   *buf = 0;
2573
2574   return buf;
2575 }
2576
2577 int get_traceframe_number()
2578 {
2579  return traceframe_number;
2580 }
2581
2582
2583 /* module initialization */
2584 void
2585 _initialize_tracepoint ()
2586 {
2587   tracepoint_chain  = 0;
2588   tracepoint_count  = 0;
2589   traceframe_number = -1;
2590   tracepoint_number = -1;
2591
2592   set_internalvar (lookup_internalvar ("tpnum"), 
2593                    value_from_longest (builtin_type_int, (LONGEST) 0));
2594   set_internalvar (lookup_internalvar ("trace_frame"), 
2595                    value_from_longest (builtin_type_int, (LONGEST) -1));
2596
2597   if (tracepoint_list.list == NULL)
2598     {
2599       tracepoint_list.listsize = 128;
2600       tracepoint_list.list = xmalloc 
2601         (tracepoint_list.listsize * sizeof (struct memrange));
2602     }
2603   if (tracepoint_list.aexpr_list == NULL)
2604     {
2605       tracepoint_list.aexpr_listsize = 128;
2606       tracepoint_list.aexpr_list = xmalloc
2607         (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *));
2608     }
2609
2610   if (stepping_list.list == NULL)
2611     {
2612       stepping_list.listsize = 128;
2613       stepping_list.list = xmalloc 
2614         (stepping_list.listsize * sizeof (struct memrange));
2615     }
2616
2617   if (stepping_list.aexpr_list == NULL)
2618     {
2619       stepping_list.aexpr_listsize = 128;
2620       stepping_list.aexpr_list = xmalloc
2621         (stepping_list.aexpr_listsize * sizeof (struct agent_expr *));
2622     }
2623
2624   add_info ("scope", scope_info, 
2625             "List the variables local to a scope");
2626
2627   add_cmd ("tracepoints", class_trace, NO_FUNCTION, 
2628            "Tracing of program execution without stopping the program.", 
2629            &cmdlist);
2630
2631   add_info ("tracepoints", tracepoints_info,
2632             "Status of tracepoints, or tracepoint number NUMBER.\n\
2633 Convenience variable \"$tpnum\" contains the number of the\n\
2634 last tracepoint set.");
2635
2636   add_info_alias ("tp", "tracepoints", 1);
2637
2638   add_com ("save-tracepoints", class_trace, tracepoint_save_command, 
2639            "Save current tracepoint definitions as a script.\n\
2640 Use the 'source' command in another debug session to restore them.");
2641
2642   add_com ("tdump", class_trace, trace_dump_command, 
2643            "Print everything collected at the current tracepoint.");
2644
2645   add_prefix_cmd ("tfind",  class_trace, trace_find_command,
2646                   "Select a trace frame;\n\
2647 No argument means forward by one frame; '-' meand backward by one frame.",
2648                   &tfindlist, "tfind ", 1, &cmdlist);
2649
2650   add_cmd ("outside", class_trace, trace_find_outside_command,
2651            "Select a trace frame whose PC is outside the given \
2652 range.\nUsage: tfind outside addr1, addr2", 
2653            &tfindlist);
2654
2655   add_cmd ("range", class_trace, trace_find_range_command,
2656            "Select a trace frame whose PC is in the given range.\n\
2657 Usage: tfind range addr1,addr2", 
2658            &tfindlist);
2659
2660   add_cmd ("line", class_trace, trace_find_line_command,
2661            "Select a trace frame by source line.\n\
2662 Argument can be a line number (with optional source file), \n\
2663 a function name, or '*' followed by an address.\n\
2664 Default argument is 'the next source line that was traced'.",
2665            &tfindlist);
2666
2667   add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
2668            "Select a trace frame by tracepoint number.\n\
2669 Default is the tracepoint for the current trace frame.",
2670            &tfindlist);
2671
2672   add_cmd ("pc", class_trace, trace_find_pc_command,
2673            "Select a trace frame by PC.\n\
2674 Default is the current PC, or the PC of the current trace frame.",
2675            &tfindlist);
2676
2677   add_cmd ("end", class_trace, trace_find_end_command,
2678            "Synonym for 'none'.\n\
2679 De-select any trace frame and resume 'live' debugging.",
2680            &tfindlist);
2681
2682   add_cmd ("none", class_trace, trace_find_none_command,
2683            "De-select any trace frame and resume 'live' debugging.",
2684            &tfindlist);
2685
2686   add_cmd ("start", class_trace, trace_find_start_command,
2687            "Select the first trace frame in the trace buffer.",
2688            &tfindlist);
2689
2690   add_com ("tstatus",  class_trace, trace_status_command,
2691            "Display the status of the current trace data collection.");
2692
2693   add_com ("tstop",  class_trace, trace_stop_command,
2694            "Stop trace data collection.");
2695
2696   add_com ("tstart", class_trace, trace_start_command,
2697            "Start trace data collection.");
2698
2699   add_com ("passcount", class_trace, trace_pass_command, 
2700            "Set the passcount for a tracepoint.\n\
2701 The trace will end when the tracepoint has been passed 'count' times.\n\
2702 Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2703 if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2704
2705   add_com ("end", class_trace, end_actions_pseudocommand,
2706            "Ends a list of commands or actions.\n\
2707 Several GDB commands allow you to enter a list of commands or actions.\n\
2708 Entering \"end\" on a line by itself is the normal way to terminate\n\
2709 such a list.\n\n\
2710 Note: the \"end\" command cannot be used at the gdb prompt.");
2711
2712   add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
2713            "Specify single-stepping behavior at a tracepoint.\n\
2714 Argument is number of instructions to trace in single-step mode\n\
2715 following the tracepoint.  This command is normally followed by\n\
2716 one or more \"collect\" commands, to specify what to collect\n\
2717 while single-stepping.\n\n\
2718 Note: this command can only be used in a tracepoint \"actions\" list.");
2719
2720   add_com_alias ("ws",         "while-stepping", class_alias, 0);
2721   add_com_alias ("stepping",   "while-stepping", class_alias, 0);
2722
2723   add_com ("collect", class_trace, collect_pseudocommand, 
2724            "Specify one or more data items to be collected at a tracepoint.\n\
2725 Accepts a comma-separated list of (one or more) expressions.  GDB will\n\
2726 collect all data (variables, registers) referenced by that expression.\n\
2727 Also accepts the following special arguments:\n\
2728     $regs   -- all registers.\n\
2729     $args   -- all function arguments.\n\
2730     $locals -- all variables local to the block/function scope.\n\
2731 Note: this command can only be used in a tracepoint \"actions\" list.");
2732
2733   add_com ("actions", class_trace, trace_actions_command,
2734            "Specify the actions to be taken at a tracepoint.\n\
2735 Tracepoint actions may include collecting of specified data, \n\
2736 single-stepping, or enabling/disabling other tracepoints, \n\
2737 depending on target's capabilities.");
2738
2739   add_cmd ("tracepoints", class_trace, delete_trace_command, 
2740            "Delete specified tracepoints.\n\
2741 Arguments are tracepoint numbers, separated by spaces.\n\
2742 No argument means delete all tracepoints.",
2743            &deletelist);
2744
2745   add_cmd ("tracepoints", class_trace, disable_trace_command, 
2746            "Disable specified tracepoints.\n\
2747 Arguments are tracepoint numbers, separated by spaces.\n\
2748 No argument means disable all tracepoints.",
2749            &disablelist);
2750
2751   add_cmd ("tracepoints", class_trace, enable_trace_command, 
2752            "Enable specified tracepoints.\n\
2753 Arguments are tracepoint numbers, separated by spaces.\n\
2754 No argument means enable all tracepoints.",
2755            &enablelist);
2756
2757   add_com ("trace", class_trace, trace_command,
2758            "Set a tracepoint at a specified line or function or address.\n\
2759 Argument may be a line number, function name, or '*' plus an address.\n\
2760 For a line number or function, trace at the start of its code.\n\
2761 If an address is specified, trace at that exact address.\n\n\
2762 Do \"help tracepoints\" for info on other tracepoint commands.");
2763
2764   add_com_alias ("tp",   "trace", class_alias, 0);
2765   add_com_alias ("tr",   "trace", class_alias, 1);
2766   add_com_alias ("tra",  "trace", class_alias, 1);
2767   add_com_alias ("trac", "trace", class_alias, 1);
2768 }
2769