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