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