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