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