OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [gdbtk/] [generic/] [gdbtk-cmds.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Tcl/Tk command definitions for Insight.
2
   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2001
3
   Free Software Foundation, Inc.
4
 
5
   Written by Stu Grossman <grossman@cygnus.com> of Cygnus Support.
6
   Substantially augmented by Martin Hunt, Keith Seitz & Jim Ingham of
7
   Cygnus Support.
8
 
9
   This file is part of GDB.
10
 
11
   This program is free software; you can redistribute it and/or modify
12
   it under the terms of the GNU General Public License as published by
13
   the Free Software Foundation; either version 2 of the License, or
14
   (at your option) any later version.
15
 
16
   This program is distributed in the hope that it will be useful,
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
   GNU General Public License for more details.
20
 
21
   You should have received a copy of the GNU General Public License
22
   along with this program; if not, write to the Free Software
23
   Foundation, Inc., 59 Temple Place - Suite 330,
24
   Boston, MA 02111-1307, USA.  */
25
 
26
#include "defs.h"
27
#include "symtab.h"
28
#include "inferior.h"
29
#include "command.h"
30
#include "source.h"
31
#include "bfd.h"
32
#include "symfile.h"
33
#include "objfiles.h"
34
#include "target.h"
35
#include "gdbcore.h"
36
#include "demangle.h"
37
#include "regcache.h"
38
#include "linespec.h"
39
#include "tui/tui-file.h"
40
 
41
#include <sys/stat.h>
42
 
43
#include <tcl.h>
44
#include <tk.h>
45
#include <itcl.h>
46
#include <tix.h>
47
#include "guitcl.h"
48
#include "gdbtk.h"
49
#include "gdbtk-wrapper.h"
50
#include "gdbtk-cmds.h"
51
 
52
#include <signal.h>
53
#include <fcntl.h>
54
#include "top.h"
55
#include <sys/ioctl.h>
56
#include "gdb_string.h"
57
#include "dis-asm.h"
58
#include <stdio.h>
59
#include "gdbcmd.h"
60
 
61
#include "annotate.h"
62
#include <sys/time.h>
63
 
64
/* Various globals we reference.  */
65
extern char *source_path;
66
 
67
/* These two objects hold boolean true and false,
68
   and are shared by all the list objects that gdb_listfuncs
69
   returns. */
70
 
71
static Tcl_Obj *mangled, *not_mangled;
72
 
73
/* These two control how the GUI behaves when gdb is either tracing or loading.
74
   They are used in this file & gdbtk_hooks.c */
75
 
76
int No_Update = 0;
77
int load_in_progress = 0;
78
 
79
/* This Structure is used in gdb_disassemble.
80
   We need a different sort of line table from the normal one cuz we can't
81
   depend upon implicit line-end pc's for lines to do the
82
   reordering in this function.  */
83
 
84
struct my_line_entry
85
  {
86
    int line;
87
    CORE_ADDR start_pc;
88
    CORE_ADDR end_pc;
89
  };
90
 
91
/* Use this to pass the Tcl Text widget command and the open file
92
   descriptor to the disassembly load command. */
93
 
94
struct disassembly_client_data {
95
  FILE *fp;
96
  int file_opened_p;
97
  int widget_line_no;
98
  Tcl_Interp *interp;
99
  char *widget;
100
  Tcl_Obj *result_obj[3];
101
  char *asm_argv[14];
102
  char *source_argv[7];
103
  char *map_arr;
104
  Tcl_DString src_to_line_prefix;
105
  Tcl_DString pc_to_line_prefix;
106
  Tcl_DString line_to_pc_prefix;
107
  Tcl_CmdInfo cmd;
108
};
109
 
110
/* This variable determines where memory used for disassembly is read from.
111
 * See note in gdbtk.h for details.
112
 */
113
int disassemble_from_exec = -1;
114
 
115
extern int gdb_variable_init (Tcl_Interp * interp);
116
 
117
/*
118
 * Declarations for routines exported from this file
119
 */
120
 
121
int Gdbtk_Init (Tcl_Interp * interp);
122
 
123
/*
124
 * Declarations for routines used only in this file.
125
 */
126
 
127
static int compare_lines (const PTR, const PTR);
128
static int comp_files (const void *, const void *);
129
static int gdb_clear_file (ClientData, Tcl_Interp * interp, int,
130
                           Tcl_Obj * CONST[]);
131
static int gdb_cmd (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
132
static int gdb_confirm_quit (ClientData, Tcl_Interp *, int,
133
                             Tcl_Obj * CONST[]);
134
static int gdb_disassemble (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
135
static int gdb_entry_point (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
136
static int gdb_eval (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
137
static int gdb_find_file_command (ClientData, Tcl_Interp *, int,
138
                                  Tcl_Obj * CONST objv[]);
139
static int gdb_force_quit (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
140
static int gdb_get_file_command (ClientData, Tcl_Interp *, int,
141
                                 Tcl_Obj * CONST objv[]);
142
static int gdb_get_function_command (ClientData, Tcl_Interp *, int,
143
                                     Tcl_Obj * CONST objv[]);
144
static int gdb_get_line_command (ClientData, Tcl_Interp *, int,
145
                                 Tcl_Obj * CONST objv[]);
146
static int gdb_get_mem (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
147
static int gdb_set_mem (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
148
static int gdb_immediate_command (ClientData, Tcl_Interp *, int,
149
                                  Tcl_Obj * CONST[]);
150
static int gdb_listfiles (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
151
static int gdb_listfuncs (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
152
static int gdb_loadfile (ClientData, Tcl_Interp *, int,
153
                         Tcl_Obj * CONST objv[]);
154
static int gdb_load_disassembly (ClientData clientData, Tcl_Interp
155
                                 * interp, int objc, Tcl_Obj * CONST objv[]);
156
static int gdb_get_inferior_args (ClientData clientData,
157
                                  Tcl_Interp *interp,
158
                                  int objc, Tcl_Obj * CONST objv[]);
159
static int gdb_set_inferior_args (ClientData clientData,
160
                                  Tcl_Interp *interp,
161
                                  int objc, Tcl_Obj * CONST objv[]);
162
static int gdb_load_info (ClientData, Tcl_Interp *, int,
163
                          Tcl_Obj * CONST objv[]);
164
static int gdb_loc (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
165
static int gdb_path_conv (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
166
static int gdb_prompt_command (ClientData, Tcl_Interp *, int,
167
                               Tcl_Obj * CONST objv[]);
168
static int gdb_restore_fputs (ClientData, Tcl_Interp *, int,
169
                              Tcl_Obj * CONST[]);
170
static int gdb_search (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST objv[]);
171
static int gdb_stop (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
172
static int gdb_target_has_execution_command (ClientData,
173
                                             Tcl_Interp *, int,
174
                                             Tcl_Obj * CONST[]);
175
static int gdbtk_dis_asm_read_memory (bfd_vma, bfd_byte *, unsigned int,
176
                                      disassemble_info *);
177
static void gdbtk_load_source (ClientData clientData,
178
                               struct symtab *symtab,
179
                               int start_line, int end_line);
180
static CORE_ADDR gdbtk_load_asm (ClientData clientData, CORE_ADDR pc,
181
                                 struct disassemble_info *di);
182
static void gdbtk_print_source (ClientData clientData,
183
                                struct symtab *symtab,
184
                                int start_line, int end_line);
185
static CORE_ADDR gdbtk_print_asm (ClientData clientData, CORE_ADDR pc,
186
                                  struct disassemble_info *di);
187
static int gdb_disassemble_driver (CORE_ADDR low, CORE_ADDR high,
188
                                   int mixed_source_and_assembly,
189
                                   ClientData clientData,
190
                                   void (*print_source_fn) (ClientData, struct
191
                                                            symtab *, int,
192
                                                            int),
193
                                   CORE_ADDR (*print_asm_fn) (ClientData,
194
                                                              CORE_ADDR,
195
                                                              struct
196
                                                              disassemble_info
197
                                                              *));
198
char *get_prompt (void);
199
static int perror_with_name_wrapper (PTR args);
200
static int wrapped_call (PTR opaque_args);
201
static int hex2bin (const char *hex, char *bin, int count);
202
static int fromhex (int a);
203
 
204
 
205
/* Gdbtk_Init
206
 *    This loads all the Tcl commands into the Tcl interpreter.
207
 *
208
 * Arguments:
209
 *    interp - The interpreter into which to load the commands.
210
 *
211
 * Result:
212
 *     A standard Tcl result.
213
 */
214
 
215
int
216
Gdbtk_Init (interp)
217
     Tcl_Interp *interp;
218
{
219
  Tcl_CreateObjCommand (interp, "gdb_cmd", gdbtk_call_wrapper, gdb_cmd, NULL);
220
  Tcl_CreateObjCommand (interp, "gdb_immediate", gdbtk_call_wrapper,
221
                        gdb_immediate_command, NULL);
222
  Tcl_CreateObjCommand (interp, "gdb_loc", gdbtk_call_wrapper, gdb_loc, NULL);
223
  Tcl_CreateObjCommand (interp, "gdb_path_conv", gdbtk_call_wrapper, gdb_path_conv,
224
                        NULL);
225
  Tcl_CreateObjCommand (interp, "gdb_listfiles", gdbtk_call_wrapper, gdb_listfiles,
226
                        NULL);
227
  Tcl_CreateObjCommand (interp, "gdb_listfuncs", gdbtk_call_wrapper, gdb_listfuncs,
228
                        NULL);
229
  Tcl_CreateObjCommand (interp, "gdb_entry_point", gdbtk_call_wrapper,
230
                        gdb_entry_point, NULL);
231
  Tcl_CreateObjCommand (interp, "gdb_get_mem", gdbtk_call_wrapper, gdb_get_mem,
232
                        NULL);
233
  Tcl_CreateObjCommand (interp, "gdb_set_mem", gdbtk_call_wrapper, gdb_set_mem,
234
                        NULL);
235
  Tcl_CreateObjCommand (interp, "gdb_stop", gdbtk_call_wrapper, gdb_stop, NULL);
236
  Tcl_CreateObjCommand (interp, "gdb_restore_fputs", gdbtk_call_wrapper, gdb_restore_fputs,
237
                        NULL);
238
  Tcl_CreateObjCommand (interp, "gdb_disassemble", gdbtk_call_wrapper,
239
                        gdb_disassemble, NULL);
240
  Tcl_CreateObjCommand (interp, "gdb_eval", gdbtk_call_wrapper, gdb_eval, NULL);
241
  Tcl_CreateObjCommand (interp, "gdb_clear_file", gdbtk_call_wrapper,
242
                        gdb_clear_file, NULL);
243
  Tcl_CreateObjCommand (interp, "gdb_confirm_quit", gdbtk_call_wrapper,
244
                        gdb_confirm_quit, NULL);
245
  Tcl_CreateObjCommand (interp, "gdb_force_quit", gdbtk_call_wrapper,
246
                        gdb_force_quit, NULL);
247
  Tcl_CreateObjCommand (interp, "gdb_target_has_execution",
248
                        gdbtk_call_wrapper,
249
                        gdb_target_has_execution_command, NULL);
250
  Tcl_CreateObjCommand (interp, "gdb_load_info", gdbtk_call_wrapper, gdb_load_info,
251
                        NULL);
252
  Tcl_CreateObjCommand (interp, "gdb_get_function", gdbtk_call_wrapper,
253
                        gdb_get_function_command, NULL);
254
  Tcl_CreateObjCommand (interp, "gdb_get_line", gdbtk_call_wrapper,
255
                        gdb_get_line_command, NULL);
256
  Tcl_CreateObjCommand (interp, "gdb_get_file", gdbtk_call_wrapper,
257
                        gdb_get_file_command, NULL);
258
  Tcl_CreateObjCommand (interp, "gdb_prompt",
259
                        gdbtk_call_wrapper, gdb_prompt_command, NULL);
260
  Tcl_CreateObjCommand (interp, "gdb_find_file",
261
                        gdbtk_call_wrapper, gdb_find_file_command, NULL);
262
  Tcl_CreateObjCommand (interp, "gdb_loadfile", gdbtk_call_wrapper, gdb_loadfile,
263
                        NULL);
264
  Tcl_CreateObjCommand (interp, "gdb_load_disassembly", gdbtk_call_wrapper,
265
                        gdb_load_disassembly,  NULL);
266
  Tcl_CreateObjCommand (gdbtk_interp, "gdb_search", gdbtk_call_wrapper,
267
                        gdb_search, NULL);
268
  Tcl_CreateObjCommand (interp, "gdb_get_inferior_args", gdbtk_call_wrapper,
269
                        gdb_get_inferior_args, NULL);
270
  Tcl_CreateObjCommand (interp, "gdb_set_inferior_args", gdbtk_call_wrapper,
271
                        gdb_set_inferior_args, NULL);
272
 
273
  /* gdb_context is used for debugging multiple threads or tasks */
274
  Tcl_LinkVar (interp, "gdb_context_id",
275
               (char *) &gdb_context,
276
               TCL_LINK_INT | TCL_LINK_READ_ONLY);
277
 
278
  /* Make gdb's notion of the pwd visible.  This is read-only because
279
     (1) it doesn't make sense to change it directly and (2) it is
280
     allocated using xmalloc and not Tcl_Alloc.  You might think we
281
     could just use the Tcl `pwd' command.  However, Tcl (erroneously,
282
     imho) maintains a cache of the current directory name, and
283
     doesn't provide a way for gdb to invalidate the cache.  */
284
  Tcl_LinkVar (interp, "gdb_current_directory",
285
               (char *) &current_directory,
286
               TCL_LINK_STRING | TCL_LINK_READ_ONLY);
287
 
288
  /* Current gdb source file search path.  This is read-only for
289
     reasons similar to those for gdb_current_directory.  */
290
  Tcl_LinkVar (interp, "gdb_source_path",
291
               (char *) &source_path,
292
               TCL_LINK_STRING | TCL_LINK_READ_ONLY);
293
 
294
  /* Init variable interface... */
295
  if (gdb_variable_init (interp) != TCL_OK)
296
    return TCL_ERROR;
297
 
298
  /* Init breakpoint module */
299
  if (Gdbtk_Breakpoint_Init (interp) != TCL_OK)
300
    return TCL_ERROR;
301
 
302
  /* Init stack module */
303
  if (Gdbtk_Stack_Init (interp) != TCL_OK)
304
    return TCL_ERROR;
305
 
306
  /* Init register module */
307
  if (Gdbtk_Register_Init (interp) != TCL_OK)
308
    return TCL_ERROR;
309
 
310
  /* Determine where to disassemble from */
311
  Tcl_LinkVar (gdbtk_interp, "disassemble-from-exec",
312
               (char *) &disassemble_from_exec,
313
               TCL_LINK_INT);
314
 
315
  Tcl_PkgProvide (interp, "Gdbtk", GDBTK_VERSION);
316
  return TCL_OK;
317
}
318
 
319
/* This routine acts as a top-level for all GDB code called by Tcl/Tk.  It
320
   handles cleanups, and uses catch_errors to trap calls to return_to_top_level
321
   (usually via error).
322
   This is necessary in order to prevent a longjmp out of the bowels of Tk,
323
   possibly leaving things in a bad state.  Since this routine can be called
324
   recursively, it needs to save and restore the contents of the result_ptr as
325
   necessary. */
326
 
327
int
328
gdbtk_call_wrapper (clientData, interp, objc, objv)
329
     ClientData clientData;
330
     Tcl_Interp *interp;
331
     int objc;
332
     Tcl_Obj *CONST objv[];
333
{
334
  struct wrapped_call_args wrapped_args;
335
  gdbtk_result new_result, *old_result_ptr;
336
  int wrapped_returned_error = 0;
337
 
338
  old_result_ptr = result_ptr;
339
  result_ptr = &new_result;
340
  result_ptr->obj_ptr = Tcl_NewObj ();
341
  result_ptr->flags = GDBTK_TO_RESULT;
342
 
343
  wrapped_args.func = (Tcl_ObjCmdProc *) clientData;
344
  wrapped_args.interp = interp;
345
  wrapped_args.objc = objc;
346
  wrapped_args.objv = objv;
347
  wrapped_args.val = TCL_OK;
348
 
349
  if (!catch_errors (wrapped_call, &wrapped_args, "", RETURN_MASK_ALL))
350
    {
351
 
352
      wrapped_args.val = TCL_ERROR;     /* Flag an error for TCL */
353
 
354
      /* Make sure the timer interrupts are turned off.  */
355
      gdbtk_stop_timer ();
356
 
357
      gdb_flush (gdb_stderr);   /* Flush error output */
358
      gdb_flush (gdb_stdout);   /* Sometimes error output comes here as well */
359
 
360
      /* If we errored out here, and the results were going to the
361
         console, then gdbtk_fputs will have gathered the result into the
362
         result_ptr.  We also need to echo them out to the console here */
363
 
364
      gdb_flush (gdb_stderr);   /* Flush error output */
365
      gdb_flush (gdb_stdout);   /* Sometimes error output comes here as well */
366
 
367
      /* In case of an error, we may need to force the GUI into idle
368
         mode because gdbtk_call_command may have bombed out while in
369
         the command routine.  */
370
 
371
      running_now = 0;
372
      Tcl_Eval (interp, "gdbtk_tcl_idle");
373
 
374
    }
375
  else
376
    {
377
      /* If the wrapped call returned an error directly, then we don't
378
         want to reset the result.  */
379
      wrapped_returned_error = wrapped_args.val == TCL_ERROR;
380
    }
381
 
382
  /* do not suppress any errors -- a remote target could have errored */
383
  load_in_progress = 0;
384
 
385
  /*
386
   * Now copy the result over to the true Tcl result.  If
387
   * GDBTK_TO_RESULT flag bit is set, this just copies a null object
388
   * over to the Tcl result, which is fine because we should reset the
389
   * result in this case anyway.  If the wrapped command returned an
390
   * error, then we assume that the result is already set correctly.
391
   */
392
  if ((result_ptr->flags & GDBTK_IN_TCL_RESULT) || wrapped_returned_error)
393
    {
394
      Tcl_DecrRefCount (result_ptr->obj_ptr);
395
    }
396
  else
397
    {
398
      Tcl_SetObjResult (interp, result_ptr->obj_ptr);
399
    }
400
 
401
  result_ptr = old_result_ptr;
402
 
403
#ifdef _WIN32
404
  close_bfds ();
405
#endif
406
 
407
  return wrapped_args.val;
408
}
409
 
410
/*
411
 * This is the wrapper that is passed to catch_errors.
412
 */
413
 
414
static int
415
wrapped_call (opaque_args)
416
     PTR opaque_args;
417
{
418
  struct wrapped_call_args *args = (struct wrapped_call_args *) opaque_args;
419
  args->val = (*args->func) (args->func, args->interp, args->objc, args->objv);
420
  return 1;
421
}
422
 
423
/* This is a convenience function to sprintf something(s) into a
424
 * new element in a Tcl list object.
425
 */
426
 
427
void
428
sprintf_append_element_to_obj (Tcl_Obj * objp, char *format,...)
429
{
430
  va_list args;
431
  char *buf;
432
 
433
  va_start (args, format);
434
 
435
  xvasprintf (&buf, format, args);
436
 
437
  Tcl_ListObjAppendElement (NULL, objp, Tcl_NewStringObj (buf, -1));
438
  free(buf);
439
}
440
 
441
/*
442
 * This section contains the commands that control execution.
443
 */
444
 
445
/* This implements the tcl command gdb_clear_file.
446
 
447
 * Prepare to accept a new executable file.  This is called when we
448
 * want to clear away everything we know about the old file, without
449
 * asking the user.  The Tcl code will have already asked the user if
450
 * necessary.  After this is called, we should be able to run the
451
 * `file' command without getting any questions.
452
 *
453
 * Arguments:
454
 *    None
455
 * Tcl Result:
456
 *    None
457
 */
458
 
459
static int
460
gdb_clear_file (clientData, interp, objc, objv)
461
     ClientData clientData;
462
     Tcl_Interp *interp;
463
     int objc;
464
     Tcl_Obj *CONST objv[];
465
{
466
  if (objc != 1)
467
    {
468
      Tcl_WrongNumArgs (interp, 1, objv, NULL);
469
      return TCL_ERROR;
470
    }
471
 
472
  if (! ptid_equal (inferior_ptid, null_ptid) && target_has_execution)
473
    {
474
      if (attach_flag)
475
        target_detach (NULL, 0);
476
      else
477
        target_kill ();
478
    }
479
 
480
  if (target_has_execution)
481
    pop_target ();
482
 
483
  delete_command (NULL, 0);
484
  exec_file_clear (0);
485
  symbol_file_clear (0);
486
 
487
  return TCL_OK;
488
}
489
 
490
/* This implements the tcl command gdb_confirm_quit
491
 * Ask the user to confirm an exit request.
492
 *
493
 * Arguments:
494
 *    None
495
 * Tcl Result:
496
 *    A boolean, 1 if the user answered yes, 0 if no.
497
 */
498
 
499
static int
500
gdb_confirm_quit (clientData, interp, objc, objv)
501
     ClientData clientData;
502
     Tcl_Interp *interp;
503
     int objc;
504
     Tcl_Obj *CONST objv[];
505
{
506
  int ret;
507
 
508
  if (objc != 1)
509
    {
510
      Tcl_WrongNumArgs (interp, 1, objv, NULL);
511
      return TCL_ERROR;
512
    }
513
 
514
  ret = quit_confirm ();
515
  Tcl_SetBooleanObj (result_ptr->obj_ptr, ret);
516
  return TCL_OK;
517
}
518
 
519
/* This implements the tcl command gdb_force_quit
520
 * Quit without asking for confirmation.
521
 *
522
 * Arguments:
523
 *    None
524
 * Tcl Result:
525
 *    None
526
 */
527
 
528
static int
529
gdb_force_quit (clientData, interp, objc, objv)
530
     ClientData clientData;
531
     Tcl_Interp *interp;
532
     int objc;
533
     Tcl_Obj *CONST objv[];
534
{
535
  if (objc != 1)
536
    {
537
      Tcl_WrongNumArgs (interp, 1, objv, NULL);
538
      return TCL_ERROR;
539
    }
540
 
541
  quit_force ((char *) NULL, 1);
542
  return TCL_OK;
543
}
544
 
545
/* Pressing the stop button on the source window should attempt to
546
 * stop the target. If, after some short time, this fails, a dialog
547
 * should appear allowing the user to detach.
548
 *
549
 * The global GDBTK_FORCE_DETACH is set when we wish to detach
550
 * from a target. This value is returned by ui_loop_hook (x_event),
551
 * indicating to callers that they should detach.
552
 *
553
 * Read the comments before x_event to find out how we (try) to keep
554
 * gdbtk alive while some other event loop has stolen control from us.
555
 */
556
 
557
/*
558
 * This command implements the tcl command gdb_stop, which
559
 * is used to either stop the target or detach.
560
 * Note that it is assumed that a simulator or native target
561
 * can ALWAYS be stopped. Doing a "detach" on them has no effect.
562
 *
563
 * Arguments:
564
 *    None or "detach"
565
 * Tcl Result:
566
 *    None
567
 */
568
 
569
static int
570
gdb_stop (clientData, interp, objc, objv)
571
     ClientData clientData;
572
     Tcl_Interp *interp;
573
     int objc;
574
     Tcl_Obj *CONST objv[];
575
{
576
  int force = 0;
577
  char *s;
578
 
579
  if (objc > 1)
580
    {
581
      s = Tcl_GetStringFromObj (objv[1], NULL);
582
      if (STREQ (s, "detach"))
583
        force = 1;
584
    }
585
 
586
  if (force)
587
    {
588
      /* Set the "forcibly detach from target" flag. x_event will
589
         return this value to callers when they should forcibly detach. */
590
      gdbtk_force_detach = 1;
591
    }
592
  else
593
    {
594
      if (target_stop != target_ignore)
595
        target_stop ();
596
      else
597
        quit_flag = 1;          /* hope something sees this */
598
    }
599
 
600
  return TCL_OK;
601
}
602
 
603
 
604
/*
605
 * This section contains Tcl commands that are wrappers for invoking
606
 * the GDB command interpreter.
607
 */
608
 
609
 
610
/* This implements the tcl command `gdb_eval'.
611
 * It uses the gdb evaluator to return the value of
612
 * an expression in the current language
613
 *
614
 * Tcl Arguments:
615
 *     expression - the expression to evaluate.
616
 * Tcl Result:
617
 *     The result of the evaluation.
618
 */
619
 
620
static int
621
gdb_eval (clientData, interp, objc, objv)
622
     ClientData clientData;
623
     Tcl_Interp *interp;
624
     int objc;
625
     Tcl_Obj *CONST objv[];
626
{
627
  struct expression *expr;
628
  struct cleanup *old_chain = NULL;
629
  value_ptr val;
630
 
631
  if (objc != 2)
632
    {
633
      Tcl_WrongNumArgs (interp, 1, objv, "expression");
634
      return TCL_ERROR;
635
    }
636
 
637
  expr = parse_expression (Tcl_GetStringFromObj (objv[1], NULL));
638
 
639
  old_chain = make_cleanup (free_current_contents, &expr);
640
 
641
  val = evaluate_expression (expr);
642
 
643
  /*
644
   * Print the result of the expression evaluation.  This will go to
645
   * eventually go to gdbtk_fputs, and from there be collected into
646
   * the Tcl result.
647
   */
648
 
649
  val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
650
             VALUE_EMBEDDED_OFFSET (val), VALUE_ADDRESS (val),
651
             gdb_stdout, 0, 0, 0, 0);
652
 
653
  do_cleanups (old_chain);
654
 
655
  return TCL_OK;
656
}
657
 
658
/* This implements the tcl command "gdb_cmd".
659
 
660
 * It sends its argument to the GDB command scanner for execution.
661
 * This command will never cause the update, idle and busy hooks to be called
662
 * within the GUI.
663
 *
664
 * Tcl Arguments:
665
 *    command - The GDB command to execute
666
 *    from_tty - 1 indicates this comes to the console.
667
 *               Pass this to the gdb command.
668
 * Tcl Result:
669
 *    The output from the gdb command (except for the "load" & "while"
670
 *    which dump their output to the console.
671
 */
672
 
673
static int
674
gdb_cmd (clientData, interp, objc, objv)
675
     ClientData clientData;
676
     Tcl_Interp *interp;
677
     int objc;
678
     Tcl_Obj *CONST objv[];
679
{
680
  int from_tty = 0;
681
 
682
  if (objc < 2 || objc > 3)
683
    {
684
      Tcl_WrongNumArgs (interp, 1, objv, "command ?from_tty?");
685
      return TCL_ERROR;
686
    }
687
 
688
  if (objc == 3)
689
    {
690
      if (Tcl_GetBooleanFromObj (NULL, objv[2], &from_tty) != TCL_OK)
691
        {
692
          Tcl_SetStringObj (result_ptr->obj_ptr, "from_tty must be a boolean.",
693
                            -1);
694
          return TCL_ERROR;
695
        }
696
    }
697
 
698
  if (running_now || load_in_progress)
699
    return TCL_OK;
700
 
701
  No_Update = 1;
702
 
703
  /* for the load instruction (and possibly others later) we
704
     set turn off the GDBTK_TO_RESULT flag bit so gdbtk_fputs()
705
     will not buffer all the data until the command is finished. */
706
 
707
  if ((strncmp ("load ", Tcl_GetStringFromObj (objv[1], NULL), 5) == 0))
708
    {
709
      result_ptr->flags &= ~GDBTK_TO_RESULT;
710
      load_in_progress = 1;
711
    }
712
 
713
  execute_command (Tcl_GetStringFromObj (objv[1], NULL), from_tty);
714
 
715
  if (load_in_progress)
716
    {
717
      load_in_progress = 0;
718
      result_ptr->flags |= GDBTK_TO_RESULT;
719
    }
720
 
721
  bpstat_do_actions (&stop_bpstat);
722
 
723
  return TCL_OK;
724
}
725
 
726
/*
727
 * This implements the tcl command "gdb_immediate"
728
 *
729
 * It does exactly the same thing as gdb_cmd, except NONE of its outut
730
 * is buffered.  This will also ALWAYS cause the busy, update, and idle
731
 * hooks to be called, contrasted with gdb_cmd, which NEVER calls them.
732
 * It turns off the GDBTK_TO_RESULT flag, which diverts the result
733
 * to the console window.
734
 *
735
 * Tcl Arguments:
736
 *    command - The GDB command to execute
737
 *    from_tty - 1 to indicate this is from the console.
738
 * Tcl Result:
739
 *    None.
740
 */
741
 
742
static int
743
gdb_immediate_command (clientData, interp, objc, objv)
744
     ClientData clientData;
745
     Tcl_Interp *interp;
746
     int objc;
747
     Tcl_Obj *CONST objv[];
748
{
749
 
750
  int from_tty = 0;
751
 
752
  if (objc < 2 || objc > 3)
753
    {
754
      Tcl_WrongNumArgs (interp, 1, objv, "command ?from_tty?");
755
      return TCL_ERROR;
756
    }
757
 
758
  if (objc == 3)
759
    {
760
      if (Tcl_GetBooleanFromObj (NULL, objv[2], &from_tty) != TCL_OK)
761
        {
762
          Tcl_SetStringObj (result_ptr->obj_ptr, "from_tty must be a boolean.",
763
                            -1);
764
          return TCL_ERROR;
765
        }
766
    }
767
 
768
  if (running_now || load_in_progress)
769
    return TCL_OK;
770
 
771
  No_Update = 0;
772
 
773
  result_ptr->flags &= ~GDBTK_TO_RESULT;
774
 
775
  execute_command (Tcl_GetStringFromObj (objv[1], NULL), from_tty);
776
 
777
  bpstat_do_actions (&stop_bpstat);
778
 
779
  result_ptr->flags |= GDBTK_TO_RESULT;
780
 
781
  return TCL_OK;
782
}
783
 
784
/* This implements the tcl command "gdb_prompt"
785
 
786
 * It returns the gdb interpreter's prompt.
787
 *
788
 * Tcl Arguments:
789
 *    None.
790
 * Tcl Result:
791
 *    The prompt.
792
 */
793
 
794
static int
795
gdb_prompt_command (clientData, interp, objc, objv)
796
     ClientData clientData;
797
     Tcl_Interp *interp;
798
     int objc;
799
     Tcl_Obj *CONST objv[];
800
{
801
  Tcl_SetStringObj (result_ptr->obj_ptr, get_prompt (), -1);
802
  return TCL_OK;
803
}
804
 
805
 
806
/*
807
 * This section contains general informational commands.
808
 */
809
 
810
/* This implements the tcl command "gdb_target_has_execution"
811
 
812
 * Tells whether the target is executing.
813
 *
814
 * Tcl Arguments:
815
 *    None
816
 * Tcl Result:
817
 *    A boolean indicating whether the target is executing.
818
 */
819
 
820
static int
821
gdb_target_has_execution_command (clientData, interp, objc, objv)
822
     ClientData clientData;
823
     Tcl_Interp *interp;
824
     int objc;
825
     Tcl_Obj *CONST objv[];
826
{
827
  int result = 0;
828
 
829
  if (target_has_execution && ! ptid_equal (inferior_ptid, null_ptid))
830
    result = 1;
831
 
832
  Tcl_SetBooleanObj (result_ptr->obj_ptr, result);
833
  return TCL_OK;
834
}
835
 
836
/* This implements the tcl command "gdb_get_inferior_args"
837
 
838
 * Returns inferior command line arguments as a string
839
 *
840
 * Tcl Arguments:
841
 *    None
842
 * Tcl Result:
843
 *    A string containing the inferior command line arguments
844
 */
845
 
846
static int
847
gdb_get_inferior_args (clientData, interp, objc, objv)
848
     ClientData clientData;
849
     Tcl_Interp *interp;
850
     int objc;
851
     Tcl_Obj *CONST objv[];
852
{
853
  if (objc != 1)
854
    {
855
      Tcl_WrongNumArgs (interp, 1, objv, NULL);
856
      return TCL_ERROR;
857
    }
858
 
859
  Tcl_SetStringObj (result_ptr->obj_ptr, get_inferior_args (), -1);
860
  return TCL_OK;
861
}
862
 
863
/* This implements the tcl command "gdb_set_inferior_args"
864
 
865
 * Sets inferior command line arguments
866
 *
867
 * Tcl Arguments:
868
 *    A string containing the inferior command line arguments
869
 * Tcl Result:
870
 *    None
871
 */
872
 
873
static int
874
gdb_set_inferior_args (clientData, interp, objc, objv)
875
     ClientData clientData;
876
     Tcl_Interp *interp;
877
     int objc;
878
     Tcl_Obj *CONST objv[];
879
{
880
  char *args;
881
 
882
  if (objc != 2)
883
    {
884
      Tcl_WrongNumArgs (interp, 1, objv, "argument");
885
      return TCL_ERROR;
886
    }
887
 
888
  args = Tcl_GetStringFromObj (objv[1], NULL);
889
 
890
  /* The xstrdup/xfree stuff is so that we maintain a coherent picture
891
     for gdb.  I would expect the accessors to do this, but they
892
     don't.  */
893
  args = xstrdup (args);
894
  args = set_inferior_args (args);
895
  xfree (args);
896
 
897
  return TCL_OK;
898
}
899
 
900
/* This implements the tcl command "gdb_load_info"
901
 
902
 * It returns information about the file about to be downloaded.
903
 *
904
 * Tcl Arguments:
905
 *    filename: The file to open & get the info on.
906
 * Tcl Result:
907
 *    A list consisting of the name and size of each section.
908
 */
909
 
910
static int
911
gdb_load_info (clientData, interp, objc, objv)
912
     ClientData clientData;
913
     Tcl_Interp *interp;
914
     int objc;
915
     Tcl_Obj *CONST objv[];
916
{
917
  bfd *loadfile_bfd;
918
  struct cleanup *old_cleanups;
919
  asection *s;
920
  Tcl_Obj *ob[2];
921
 
922
  char *filename = Tcl_GetStringFromObj (objv[1], NULL);
923
 
924
  loadfile_bfd = bfd_openr (filename, gnutarget);
925
  if (loadfile_bfd == NULL)
926
    {
927
      Tcl_SetStringObj (result_ptr->obj_ptr, "Open failed", -1);
928
      return TCL_ERROR;
929
    }
930
  old_cleanups = make_cleanup_bfd_close (loadfile_bfd);
931
 
932
  if (!bfd_check_format (loadfile_bfd, bfd_object))
933
    {
934
      Tcl_SetStringObj (result_ptr->obj_ptr, "Bad Object File", -1);
935
      return TCL_ERROR;
936
    }
937
 
938
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
939
 
940
  for (s = loadfile_bfd->sections; s; s = s->next)
941
    {
942
      if (s->flags & SEC_LOAD)
943
        {
944
          bfd_size_type size = bfd_get_section_size_before_reloc (s);
945
          if (size > 0)
946
            {
947
              ob[0] = Tcl_NewStringObj ((char *)
948
                                        bfd_get_section_name (loadfile_bfd, s),
949
                                        -1);
950
              ob[1] = Tcl_NewLongObj ((long) size);
951
              Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
952
                                        Tcl_NewListObj (2, ob));
953
            }
954
        }
955
    }
956
 
957
  do_cleanups (old_cleanups);
958
  return TCL_OK;
959
}
960
 
961
 
962
/* This implements the tcl command "gdb_get_line"
963
 
964
 * It returns the linenumber for a given linespec.  It will take any spec
965
 * that can be passed to decode_line_1
966
 *
967
 * Tcl Arguments:
968
 *    linespec - the line specification
969
 * Tcl Result:
970
 *    The line number for that spec.
971
 */
972
static int
973
gdb_get_line_command (clientData, interp, objc, objv)
974
     ClientData clientData;
975
     Tcl_Interp *interp;
976
     int objc;
977
     Tcl_Obj *CONST objv[];
978
{
979
  struct symtabs_and_lines sals;
980
  char *args, **canonical;
981
 
982
  if (objc != 2)
983
    {
984
      Tcl_WrongNumArgs (interp, 1, objv, "linespec");
985
      return TCL_ERROR;
986
    }
987
 
988
  args = Tcl_GetStringFromObj (objv[1], NULL);
989
  sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
990
  if (sals.nelts == 1)
991
    {
992
      Tcl_SetIntObj (result_ptr->obj_ptr, sals.sals[0].line);
993
      return TCL_OK;
994
    }
995
 
996
  Tcl_SetStringObj (result_ptr->obj_ptr, "N/A", -1);
997
  return TCL_OK;
998
 
999
}
1000
 
1001
/* This implements the tcl command "gdb_get_file"
1002
 
1003
 * It returns the file containing a given line spec.
1004
 *
1005
 * Tcl Arguments:
1006
 *    linespec - The linespec to look up
1007
 * Tcl Result:
1008
 *    The file containing it.
1009
 */
1010
 
1011
static int
1012
gdb_get_file_command (clientData, interp, objc, objv)
1013
     ClientData clientData;
1014
     Tcl_Interp *interp;
1015
     int objc;
1016
     Tcl_Obj *CONST objv[];
1017
{
1018
  struct symtabs_and_lines sals;
1019
  char *args, **canonical;
1020
 
1021
  if (objc != 2)
1022
    {
1023
      Tcl_WrongNumArgs (interp, 1, objv, "linespec");
1024
      return TCL_ERROR;
1025
    }
1026
 
1027
  args = Tcl_GetStringFromObj (objv[1], NULL);
1028
  sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
1029
  if (sals.nelts == 1)
1030
    {
1031
      Tcl_SetStringObj (result_ptr->obj_ptr,
1032
                        sals.sals[0].symtab->filename, -1);
1033
      return TCL_OK;
1034
    }
1035
 
1036
  Tcl_SetStringObj (result_ptr->obj_ptr, "N/A", -1);
1037
  return TCL_OK;
1038
}
1039
 
1040
/* This implements the tcl command "gdb_get_function"
1041
 
1042
 * It finds the function containing the given line spec.
1043
 *
1044
 * Tcl Arguments:
1045
 *    linespec - The line specification
1046
 * Tcl Result:
1047
 *    The function that contains it, or "N/A" if it is not in a function.
1048
 */
1049
static int
1050
gdb_get_function_command (clientData, interp, objc, objv)
1051
     ClientData clientData;
1052
     Tcl_Interp *interp;
1053
     int objc;
1054
     Tcl_Obj *CONST objv[];
1055
{
1056
  char *function;
1057
  struct symtabs_and_lines sals;
1058
  char *args, **canonical;
1059
 
1060
  if (objc != 2)
1061
    {
1062
      Tcl_WrongNumArgs (interp, 1, objv, "linespec");
1063
      return TCL_ERROR;
1064
    }
1065
 
1066
  args = Tcl_GetStringFromObj (objv[1], NULL);
1067
  sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
1068
  if (sals.nelts == 1)
1069
    {
1070
      resolve_sal_pc (&sals.sals[0]);
1071
      function = pc_function_name (sals.sals[0].pc);
1072
      Tcl_SetStringObj (result_ptr->obj_ptr, function, -1);
1073
      return TCL_OK;
1074
    }
1075
 
1076
  Tcl_SetStringObj (result_ptr->obj_ptr, "N/A", -1);
1077
  return TCL_OK;
1078
}
1079
 
1080
/* This implements the tcl command "gdb_find_file"
1081
 
1082
 * It searches the symbol tables to get the full pathname to a file.
1083
 *
1084
 * Tcl Arguments:
1085
 *    filename: the file name to search for.
1086
 * Tcl Result:
1087
 *    The full path to the file, an empty string if the file was not
1088
 *    available or an error message if the file is not found in the symtab.
1089
 */
1090
 
1091
static int
1092
gdb_find_file_command (clientData, interp, objc, objv)
1093
     ClientData clientData;
1094
     Tcl_Interp *interp;
1095
     int objc;
1096
     Tcl_Obj *CONST objv[];
1097
{
1098
  struct symtab *st;
1099
  char *filename;
1100
 
1101
  if (objc != 2)
1102
    {
1103
      Tcl_WrongNumArgs (interp, 1, objv, "filename");
1104
      return TCL_ERROR;
1105
    }
1106
 
1107
  filename = Tcl_GetStringFromObj (objv[1], NULL);
1108
  st = full_lookup_symtab (filename);
1109
 
1110
  /* We should always get a symtab. */
1111
  if (!st)
1112
    {
1113
      Tcl_SetStringObj ( result_ptr->obj_ptr,
1114
                         "File not found in symtab (2)", -1);
1115
      return TCL_ERROR;
1116
    }
1117
 
1118
  /* We may not be able to open the file (not available). */
1119
  if (!st->fullname)
1120
    {
1121
      Tcl_SetStringObj (result_ptr->obj_ptr, "", -1);
1122
      return TCL_OK;
1123
    }
1124
 
1125
  Tcl_SetStringObj (result_ptr->obj_ptr, st->fullname, -1);
1126
 
1127
  return TCL_OK;
1128
}
1129
 
1130
/* This implements the tcl command "gdb_listfiles"
1131
 
1132
 * This lists all the files in the current executible.
1133
 *
1134
 * Note that this currently pulls in all sorts of filenames
1135
 * that aren't really part of the executable.  It would be
1136
 * best if we could check each file to see if it actually
1137
 * contains executable lines of code, but we can't do that
1138
 * with psymtabs.
1139
 *
1140
 * Arguments:
1141
 *    ?pathname? - If provided, only files which match pathname
1142
 *        (up to strlen(pathname)) are included. THIS DOES NOT
1143
 *        CURRENTLY WORK BECAUSE PARTIAL_SYMTABS DON'T SUPPLY
1144
 *        THE FULL PATHNAME!!!
1145
 *
1146
 * Tcl Result:
1147
 *    A list of all matching files.
1148
 */
1149
static int
1150
gdb_listfiles (clientData, interp, objc, objv)
1151
     ClientData clientData;
1152
     Tcl_Interp *interp;
1153
     int objc;
1154
     Tcl_Obj *CONST objv[];
1155
{
1156
  struct objfile *objfile;
1157
  struct partial_symtab *psymtab;
1158
  struct symtab *symtab;
1159
  char *lastfile, *pathname = NULL, **files;
1160
  int files_size;
1161
  int i, numfiles = 0, len = 0;
1162
 
1163
  files_size = 1000;
1164
  files = (char **) xmalloc (sizeof (char *) * files_size);
1165
 
1166
  if (objc > 2)
1167
    {
1168
      Tcl_WrongNumArgs (interp, 1, objv, "?pathname?");
1169
      return TCL_ERROR;
1170
    }
1171
  else if (objc == 2)
1172
    pathname = Tcl_GetStringFromObj (objv[1], &len);
1173
 
1174
  ALL_PSYMTABS (objfile, psymtab)
1175
  {
1176
    if (numfiles == files_size)
1177
      {
1178
        files_size = files_size * 2;
1179
        files = (char **) xrealloc (files, sizeof (char *) * files_size);
1180
      }
1181
    if (psymtab->filename)
1182
      {
1183
        if (!len || !strncmp (pathname, psymtab->filename, len)
1184
            || !strcmp (psymtab->filename, basename (psymtab->filename)))
1185
          {
1186
            files[numfiles++] = basename (psymtab->filename);
1187
          }
1188
      }
1189
  }
1190
 
1191
  ALL_SYMTABS (objfile, symtab)
1192
  {
1193
    if (numfiles == files_size)
1194
      {
1195
        files_size = files_size * 2;
1196
        files = (char **) xrealloc (files, sizeof (char *) * files_size);
1197
      }
1198
    if (symtab->filename && symtab->linetable && symtab->linetable->nitems)
1199
      {
1200
        if (!len || !strncmp (pathname, symtab->filename, len)
1201
            || !strcmp (symtab->filename, basename (symtab->filename)))
1202
          {
1203
            files[numfiles++] = basename (symtab->filename);
1204
          }
1205
      }
1206
  }
1207
 
1208
  qsort (files, numfiles, sizeof (char *), comp_files);
1209
 
1210
  lastfile = "";
1211
 
1212
  /* Discard the old result pointer, in case it has accumulated anything
1213
     and set it to a new list object */
1214
 
1215
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
1216
 
1217
  for (i = 0; i < numfiles; i++)
1218
    {
1219
      if (strcmp (files[i], lastfile))
1220
        Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
1221
                                  Tcl_NewStringObj (files[i], -1));
1222
      lastfile = files[i];
1223
    }
1224
 
1225
  free (files);
1226
  return TCL_OK;
1227
}
1228
 
1229
static int
1230
comp_files (file1, file2)
1231
     const void *file1, *file2;
1232
{
1233
  return strcmp (*(char **) file1, *(char **) file2);
1234
}
1235
 
1236
 
1237
/* This implements the tcl command "gdb_search"
1238
 
1239
 
1240
 * Tcl Arguments:
1241
 *    option - One of "functions", "variables" or "types"
1242
 *    regexp - The regular expression to look for.
1243
 * Then, optionally:
1244
 *    -files fileList
1245
 *    -static 1/0
1246
 *    -filename 1/0
1247
 * Tcl Result:
1248
 *    A list of all the matches found.  Optionally, if -filename is set to 1,
1249
 *    then the output is a list of two element lists, with the symbol first,
1250
 *    and the file in which it is found second.
1251
 */
1252
 
1253
static int
1254
gdb_search (clientData, interp, objc, objv)
1255
     ClientData clientData;
1256
     Tcl_Interp *interp;
1257
     int objc;
1258
     Tcl_Obj *CONST objv[];
1259
{
1260
  struct symbol_search *ss = NULL;
1261
  struct symbol_search *p;
1262
  struct cleanup *old_chain = NULL;
1263
  Tcl_Obj *CONST * switch_objv;
1264
  int index, switch_objc, i, show_files = 0;
1265
  namespace_enum space = 0;
1266
  char *regexp;
1267
  int static_only, nfiles;
1268
  Tcl_Obj **file_list;
1269
  char **files;
1270
  static char *search_options[] =
1271
  {"functions", "variables", "types", (char *) NULL};
1272
  static char *switches[] =
1273
  {"-files", "-filename", "-static", (char *) NULL};
1274
  enum search_opts
1275
    {
1276
      SEARCH_FUNCTIONS, SEARCH_VARIABLES, SEARCH_TYPES
1277
    };
1278
  enum switches_opts
1279
    {
1280
      SWITCH_FILES, SWITCH_FILENAME, SWITCH_STATIC_ONLY
1281
    };
1282
 
1283
  if (objc < 3)
1284
    {
1285
      Tcl_WrongNumArgs (interp, 1, objv, "option regexp ?arg ...?");
1286
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1287
      return TCL_ERROR;
1288
    }
1289
 
1290
  if (Tcl_GetIndexFromObj (interp, objv[1], search_options, "option", 0,
1291
                           &index) != TCL_OK)
1292
    {
1293
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1294
      return TCL_ERROR;
1295
    }
1296
 
1297
  /* Unfortunately, we cannot teach search_symbols to search on
1298
     multiple regexps, so we have to do a two-tier search for
1299
     any searches which choose to narrow the playing field. */
1300
  switch ((enum search_opts) index)
1301
    {
1302
    case SEARCH_FUNCTIONS:
1303
      space = FUNCTIONS_NAMESPACE;
1304
      break;
1305
    case SEARCH_VARIABLES:
1306
      space = VARIABLES_NAMESPACE;
1307
      break;
1308
    case SEARCH_TYPES:
1309
      space = TYPES_NAMESPACE;
1310
      break;
1311
    }
1312
 
1313
  regexp = Tcl_GetStringFromObj (objv[2], NULL);
1314
  /* Process any switches that refine the search */
1315
  switch_objc = objc - 3;
1316
  switch_objv = objv + 3;
1317
 
1318
  static_only = 0;
1319
  nfiles = 0;
1320
  files = (char **) NULL;
1321
  while (switch_objc > 0)
1322
    {
1323
      if (Tcl_GetIndexFromObj (interp, switch_objv[0], switches,
1324
                               "option", 0, &index) != TCL_OK)
1325
        {
1326
          result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1327
          return TCL_ERROR;
1328
        }
1329
 
1330
      switch ((enum switches_opts) index)
1331
        {
1332
        case SWITCH_FILENAME:
1333
          {
1334
            if (switch_objc < 2)
1335
              {
1336
                Tcl_WrongNumArgs (interp, 3, objv,
1337
                                  "?-files fileList  -filename 1|0 -static 1|0?");
1338
                result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1339
                return TCL_ERROR;
1340
              }
1341
            if (Tcl_GetBooleanFromObj (interp, switch_objv[1], &show_files)
1342
                != TCL_OK)
1343
              {
1344
                result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1345
                return TCL_ERROR;
1346
              }
1347
            switch_objc--;
1348
            switch_objv++;
1349
          }
1350
          break;
1351
        case SWITCH_FILES:
1352
          {
1353
            int result;
1354
            if (switch_objc < 2)
1355
              {
1356
                Tcl_WrongNumArgs (interp, 3, objv,
1357
                                  "?-files fileList  -filename 1|0 -static 1|0?");
1358
                result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1359
                return TCL_ERROR;
1360
              }
1361
            result = Tcl_ListObjGetElements (interp, switch_objv[1],
1362
                                             &nfiles, &file_list);
1363
            if (result != TCL_OK)
1364
              return result;
1365
 
1366
            files = (char **) xmalloc (nfiles * sizeof (char *));
1367
            for (i = 0; i < nfiles; i++)
1368
              files[i] = Tcl_GetStringFromObj (file_list[i], NULL);
1369
            switch_objc--;
1370
            switch_objv++;
1371
          }
1372
          break;
1373
        case SWITCH_STATIC_ONLY:
1374
          if (switch_objc < 2)
1375
            {
1376
              Tcl_WrongNumArgs (interp, 3, objv,
1377
                                "?-files fileList  -filename 1|0 -static 1|0?");
1378
              result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1379
              return TCL_ERROR;
1380
            }
1381
          if (Tcl_GetBooleanFromObj (interp, switch_objv[1], &static_only)
1382
              != TCL_OK)
1383
            {
1384
              result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1385
              return TCL_ERROR;
1386
            }
1387
          switch_objc--;
1388
          switch_objv++;
1389
        }
1390
      switch_objc--;
1391
      switch_objv++;
1392
    }
1393
 
1394
  search_symbols (regexp, space, nfiles, files, &ss);
1395
  if (ss != NULL)
1396
    old_chain = make_cleanup_free_search_symbols (ss);
1397
 
1398
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
1399
 
1400
  for (p = ss; p != NULL; p = p->next)
1401
    {
1402
      Tcl_Obj *elem;
1403
 
1404
      if (static_only && p->block != STATIC_BLOCK)
1405
        continue;
1406
 
1407
      /* Strip off some C++ special symbols, like RTTI and global
1408
         constructors/destructors. */
1409
      if ((p->symbol != NULL && !STREQN (SYMBOL_NAME (p->symbol), "__tf", 4)
1410
           && !STREQN (SYMBOL_NAME (p->symbol), "_GLOBAL_", 8))
1411
          || p->msymbol != NULL)
1412
        {
1413
          elem = Tcl_NewListObj (0, NULL);
1414
 
1415
          if (p->msymbol == NULL)
1416
            Tcl_ListObjAppendElement (interp, elem,
1417
                     Tcl_NewStringObj (SYMBOL_SOURCE_NAME (p->symbol), -1));
1418
          else
1419
            Tcl_ListObjAppendElement (interp, elem,
1420
                    Tcl_NewStringObj (SYMBOL_SOURCE_NAME (p->msymbol), -1));
1421
 
1422
          if (show_files)
1423
            {
1424
              if ((p->symtab != NULL) && (p->symtab->filename != NULL))
1425
                {
1426
                  Tcl_ListObjAppendElement (interp, elem, Tcl_NewStringObj
1427
                                            (p->symtab->filename, -1));
1428
                }
1429
              else
1430
                {
1431
                  Tcl_ListObjAppendElement (interp, elem,
1432
                                            Tcl_NewStringObj ("", 0));
1433
                }
1434
            }
1435
 
1436
          Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, elem);
1437
        }
1438
    }
1439
 
1440
  if (ss != NULL)
1441
    do_cleanups (old_chain);
1442
 
1443
  return TCL_OK;
1444
}
1445
 
1446
/* This implements the tcl command gdb_listfuncs
1447
 
1448
 * It lists all the functions defined in a given file
1449
 *
1450
 * Arguments:
1451
 *    file - the file to look in
1452
 * Tcl Result:
1453
 *    A list of two element lists, the first element is
1454
 *    the symbol name, and the second is a boolean indicating
1455
 *    whether the symbol is demangled (1 for yes).
1456
 */
1457
 
1458
static int
1459
gdb_listfuncs (clientData, interp, objc, objv)
1460
     ClientData clientData;
1461
     Tcl_Interp *interp;
1462
     int objc;
1463
     Tcl_Obj *CONST objv[];
1464
{
1465
  struct symtab *symtab;
1466
  struct blockvector *bv;
1467
  struct block *b;
1468
  struct symbol *sym;
1469
  int i, j;
1470
  Tcl_Obj *funcVals[2];
1471
 
1472
  if (objc != 2)
1473
    {
1474
      Tcl_WrongNumArgs (interp, 1, objv, "file");
1475
      return TCL_ERROR;
1476
    }
1477
 
1478
  symtab = full_lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL));
1479
  if (!symtab)
1480
    {
1481
      Tcl_SetStringObj (result_ptr->obj_ptr, "No such file", -1);
1482
      return TCL_ERROR;
1483
    }
1484
 
1485
  if (mangled == NULL)
1486
    {
1487
      mangled = Tcl_NewBooleanObj (1);
1488
      not_mangled = Tcl_NewBooleanObj (0);
1489
      Tcl_IncrRefCount (mangled);
1490
      Tcl_IncrRefCount (not_mangled);
1491
    }
1492
 
1493
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
1494
 
1495
  bv = BLOCKVECTOR (symtab);
1496
  for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
1497
    {
1498
      b = BLOCKVECTOR_BLOCK (bv, i);
1499
      /* Skip the sort if this block is always sorted.  */
1500
      if (!BLOCK_SHOULD_SORT (b))
1501
        sort_block_syms (b);
1502
      for (j = 0; j < BLOCK_NSYMS (b); j++)
1503
        {
1504
          sym = BLOCK_SYM (b, j);
1505
          if (SYMBOL_CLASS (sym) == LOC_BLOCK)
1506
            {
1507
 
1508
              char *name = SYMBOL_DEMANGLED_NAME (sym);
1509
 
1510
              if (name)
1511
                {
1512
                  /* strip out "global constructors" and
1513
                   * "global destructors"
1514
                   * because we aren't interested in them. */
1515
 
1516
                  if (strncmp (name, "global ", 7))
1517
                    {
1518
                      /* If the function is overloaded,
1519
                       * print out the functions
1520
                       * declaration, not just its name. */
1521
 
1522
                      funcVals[0] = Tcl_NewStringObj (name, -1);
1523
                      funcVals[1] = mangled;
1524
                    }
1525
                  else
1526
                    continue;
1527
 
1528
                }
1529
              else
1530
                {
1531
                  funcVals[0] = Tcl_NewStringObj (SYMBOL_NAME (sym), -1);
1532
                  funcVals[1] = not_mangled;
1533
                }
1534
              Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
1535
                                        Tcl_NewListObj (2, funcVals));
1536
            }
1537
        }
1538
    }
1539
  return TCL_OK;
1540
}
1541
 
1542
/* This implements the TCL command `gdb_restore_fputs'
1543
   It sets the fputs_unfiltered hook back to gdbtk_fputs.
1544
   Its sole reason for being is that sometimes we move the
1545
   fputs hook out of the way to specially trap output, and if
1546
   we get an error which we weren't expecting, it won't get put
1547
   back, so we run this at idle time as insurance.
1548
 */
1549
 
1550
static int
1551
gdb_restore_fputs (clientData, interp, objc, objv)
1552
     ClientData clientData;
1553
     Tcl_Interp *interp;
1554
     int objc;
1555
     Tcl_Obj *CONST objv[];
1556
{
1557
  gdbtk_disable_fputs = 0;
1558
  return TCL_OK;
1559
}
1560
 
1561
/*
1562
 * This section has commands that handle source disassembly.
1563
 */
1564
/* This implements the tcl command gdb_disassemble.  It is no longer
1565
 * used in GDBTk, we use gdb_load_disassembly, but I kept it around in
1566
 * case other folks want it.
1567
 *
1568
 * Arguments:
1569
 *    source_with_assm - must be "source" or "nosource"
1570
 *    low_address - the address from which to start disassembly
1571
 *    ?hi_address? - the address to which to disassemble, defaults
1572
 *                   to the end of the function containing low_address.
1573
 * Tcl Result:
1574
 *    The disassembled code is passed to fputs_unfiltered, so it
1575
 *    either goes to the console if result_ptr->obj_ptr is NULL or to
1576
 *    the Tcl result.
1577
 */
1578
 
1579
static int
1580
gdb_disassemble (clientData, interp, objc, objv)
1581
     ClientData clientData;
1582
     Tcl_Interp *interp;
1583
     int objc;
1584
     Tcl_Obj *CONST objv[];
1585
{
1586
  CORE_ADDR low, high;
1587
  char *arg_ptr;
1588
  int mixed_source_and_assembly;
1589
 
1590
  if (objc != 3 && objc != 4)
1591
    {
1592
      Tcl_WrongNumArgs (interp, 1, objv, "source lowaddr ?highaddr?");
1593
      return TCL_ERROR;
1594
    }
1595
 
1596
  arg_ptr = Tcl_GetStringFromObj (objv[1], NULL);
1597
  if (*arg_ptr == 's' && strcmp (arg_ptr, "source") == 0)
1598
    mixed_source_and_assembly = 1;
1599
  else if (*arg_ptr == 'n' && strcmp (arg_ptr, "nosource") == 0)
1600
    mixed_source_and_assembly = 0;
1601
  else
1602
    error ("First arg must be 'source' or 'nosource'");
1603
 
1604
  low = parse_and_eval_address (Tcl_GetStringFromObj (objv[2], NULL));
1605
 
1606
  if (objc == 3)
1607
    {
1608
      if (find_pc_partial_function (low, NULL, &low, &high) == 0)
1609
        error ("No function contains specified address");
1610
    }
1611
  else
1612
    high = parse_and_eval_address (Tcl_GetStringFromObj (objv[3], NULL));
1613
 
1614
  return gdb_disassemble_driver (low, high, mixed_source_and_assembly, NULL,
1615
                          gdbtk_print_source, gdbtk_print_asm);
1616
 
1617
}
1618
 
1619
/* This implements the tcl command gdb_load_disassembly
1620
 *
1621
 * Arguments:
1622
 *    widget - the name of a text widget into which to load the data
1623
 *    source_with_assm - must be "source" or "nosource"
1624
 *    low_address - the address from which to start disassembly
1625
 *    ?hi_address? - the address to which to disassemble, defaults
1626
 *                   to the end of the function containing low_address.
1627
 * Tcl Result:
1628
 *    The text widget is loaded with the data, and a list is returned.
1629
 *    The first element of the list is a two element list containing the
1630
 *    real low & high elements, the rest is a mapping between line number
1631
 *    in the text widget, and either the source line number of that line,
1632
 *    if it is a source line, or the assembly address.  You can distinguish
1633
 *    between the two, because the address will start with 0x...
1634
 */
1635
 
1636
static int
1637
gdb_load_disassembly (ClientData clientData, Tcl_Interp *interp,
1638
                      int objc, Tcl_Obj *CONST objv[])
1639
{
1640
  CORE_ADDR low, high;
1641
  struct disassembly_client_data client_data;
1642
  int mixed_source_and_assembly, ret_val, i;
1643
  char *arg_ptr;
1644
  char *map_name;
1645
 
1646
  if (objc != 6 && objc != 7)
1647
    {
1648
      Tcl_WrongNumArgs (interp, 1, objv, "[source|nosource] map_arr index_prefix low_address ?hi_address");
1649
      return TCL_ERROR;
1650
    }
1651
 
1652
  client_data.widget = Tcl_GetStringFromObj (objv[1], NULL);
1653
  if ( Tk_NameToWindow (interp, client_data.widget,
1654
                        Tk_MainWindow (interp)) == NULL)
1655
    {
1656
      Tcl_SetStringObj (result_ptr->obj_ptr, "Invalid widget name.", -1);
1657
      return TCL_ERROR;
1658
    }
1659
 
1660
  if (!Tcl_GetCommandInfo (interp, client_data.widget, &client_data.cmd))
1661
    {
1662
      Tcl_SetStringObj (result_ptr->obj_ptr, "Can't get widget command info",
1663
                        -1);
1664
      return TCL_ERROR;
1665
    }
1666
 
1667
  arg_ptr = Tcl_GetStringFromObj (objv[2], NULL);
1668
  if (*arg_ptr == 's' && strcmp (arg_ptr, "source") == 0)
1669
    mixed_source_and_assembly = 1;
1670
  else if (*arg_ptr == 'n' && strcmp (arg_ptr, "nosource") == 0)
1671
    mixed_source_and_assembly = 0;
1672
  else
1673
    {
1674
      Tcl_SetStringObj (result_ptr->obj_ptr,
1675
                        "Second arg must be 'source' or 'nosource'", -1);
1676
      return TCL_ERROR;
1677
    }
1678
 
1679
  /* As we populate the text widget, we will also create an array in the
1680
     caller's scope.  The name is given by objv[3].
1681
     Each source line gets an entry or the form:
1682
         array($prefix,srcline=$src_line_no) = $widget_line_no
1683
 
1684
     Each assembly line gets two entries of the form:
1685
         array($prefix,pc=$pc) = $widget_line_no
1686
         array($prefix,line=$widget_line_no) = $src_line_no
1687
 
1688
     Where prefix is objv[4].
1689
  */
1690
 
1691
  map_name = Tcl_GetStringFromObj (objv[3], NULL);
1692
 
1693
  if (*map_name != '\0')
1694
    {
1695
      char *prefix;
1696
      int prefix_len;
1697
 
1698
      client_data.map_arr = "map_array";
1699
      if (Tcl_UpVar (interp, "1", map_name, client_data.map_arr, 0) != TCL_OK) {
1700
        Tcl_SetStringObj (result_ptr->obj_ptr, "Can't link map array.", -1);
1701
        return TCL_ERROR;
1702
      }
1703
 
1704
      prefix = Tcl_GetStringFromObj (objv[4], &prefix_len);
1705
 
1706
      Tcl_DStringInit(&client_data.src_to_line_prefix);
1707
      Tcl_DStringAppend (&client_data.src_to_line_prefix,
1708
                         prefix, prefix_len);
1709
      Tcl_DStringAppend (&client_data.src_to_line_prefix, ",srcline=",
1710
                                 sizeof (",srcline=") - 1);
1711
 
1712
      Tcl_DStringInit(&client_data.pc_to_line_prefix);
1713
      Tcl_DStringAppend (&client_data.pc_to_line_prefix,
1714
                         prefix, prefix_len);
1715
      Tcl_DStringAppend (&client_data.pc_to_line_prefix, ",pc=",
1716
                         sizeof (",pc=") - 1);
1717
 
1718
      Tcl_DStringInit(&client_data.line_to_pc_prefix);
1719
      Tcl_DStringAppend (&client_data.line_to_pc_prefix,
1720
                         prefix, prefix_len);
1721
      Tcl_DStringAppend (&client_data.line_to_pc_prefix, ",line=",
1722
                         sizeof (",line=") - 1);
1723
 
1724
    }
1725
  else
1726
    {
1727
      client_data.map_arr = "";
1728
    }
1729
 
1730
  /* Now parse the addresses */
1731
 
1732
  low = parse_and_eval_address (Tcl_GetStringFromObj (objv[5], NULL));
1733
 
1734
  if (objc == 6)
1735
    {
1736
      if (find_pc_partial_function (low, NULL, &low, &high) == 0)
1737
        error ("No function contains specified address");
1738
    }
1739
  else
1740
    high = parse_and_eval_address (Tcl_GetStringFromObj (objv[6], NULL));
1741
 
1742
 
1743
  /* Setup the client_data structure, and call the driver function. */
1744
 
1745
  client_data.file_opened_p = 0;
1746
  client_data.widget_line_no = 0;
1747
  client_data.interp = interp;
1748
  for (i = 0; i < 3; i++)
1749
    {
1750
      client_data.result_obj[i] = Tcl_NewObj();
1751
      Tcl_IncrRefCount (client_data.result_obj[i]);
1752
    }
1753
 
1754
  /* Fill up the constant parts of the argv structures */
1755
  client_data.asm_argv[0] = client_data.widget;
1756
  client_data.asm_argv[1] = "insert";
1757
  client_data.asm_argv[2] = "end";
1758
  client_data.asm_argv[3] = "-\t";
1759
  client_data.asm_argv[4] = "break_rgn_tag";
1760
  /* client_data.asm_argv[5] = address; */
1761
  client_data.asm_argv[6] = "break_rgn_tag";
1762
  /* client_data.asm_argv[7] = offset; */
1763
  client_data.asm_argv[8] = "break_rgn_tag";
1764
  client_data.asm_argv[9] = ":\t\t";
1765
  client_data.asm_argv[10] = "source_tag";
1766
  /* client_data.asm_argv[11] = code; */
1767
  client_data.asm_argv[12] = "source_tag";
1768
  client_data.asm_argv[13] = "\n";
1769
 
1770
  if (mixed_source_and_assembly)
1771
    {
1772
      client_data.source_argv[0] = client_data.widget;
1773
      client_data.source_argv[1] = "insert";
1774
      client_data.source_argv[2] = "end";
1775
      /* client_data.source_argv[3] = line_number; */
1776
      client_data.source_argv[4] = "";
1777
      /* client_data.source_argv[5] = line; */
1778
      client_data.source_argv[6] = "source_tag2";
1779
    }
1780
 
1781
  ret_val = gdb_disassemble_driver (low, high, mixed_source_and_assembly,
1782
                          (ClientData) &client_data,
1783
                          gdbtk_load_source, gdbtk_load_asm);
1784
 
1785
  /* Now clean up the opened file, and the Tcl data structures */
1786
 
1787
  if (client_data.file_opened_p == 1) {
1788
    fclose(client_data.fp);
1789
  }
1790
  if (*client_data.map_arr != '\0')
1791
    {
1792
      Tcl_DStringFree(&client_data.src_to_line_prefix);
1793
      Tcl_DStringFree(&client_data.pc_to_line_prefix);
1794
      Tcl_DStringFree(&client_data.line_to_pc_prefix);
1795
    }
1796
 
1797
  for (i = 0; i < 3; i++)
1798
    {
1799
      Tcl_DecrRefCount (client_data.result_obj[i]);
1800
    }
1801
 
1802
  /* Finally, if we were successful, stick the low & high addresses
1803
     into the Tcl result. */
1804
 
1805
  if (ret_val == TCL_OK) {
1806
    char *buffer;
1807
    Tcl_Obj *limits_obj[2];
1808
 
1809
    xasprintf (&buffer, "0x%s", paddr_nz (low));
1810
    limits_obj[0] = Tcl_NewStringObj (buffer, -1);
1811
    free(buffer);
1812
 
1813
    xasprintf (&buffer, "0x%s", paddr_nz (high));
1814
    limits_obj[1] = Tcl_NewStringObj (buffer, -1);
1815
    free(buffer);
1816
 
1817
    Tcl_DecrRefCount (result_ptr->obj_ptr);
1818
    result_ptr->obj_ptr = Tcl_NewListObj (2, limits_obj);
1819
 
1820
  }
1821
  return ret_val;
1822
 
1823
}
1824
 
1825
static void
1826
gdbtk_load_source (ClientData clientData, struct symtab *symtab, int
1827
                      start_line, int end_line)
1828
{
1829
  struct disassembly_client_data *client_data =
1830
    (struct disassembly_client_data *) clientData;
1831
  char *buffer;
1832
  int index_len;
1833
 
1834
  index_len = Tcl_DStringLength (&client_data->src_to_line_prefix);
1835
 
1836
  if (client_data->file_opened_p == 1)
1837
    {
1838
      char **text_argv;
1839
      char line[10000], line_number[18];
1840
      int found_carriage_return = 1;
1841
 
1842
      /* First do some sanity checks on the requested lines */
1843
 
1844
      if (start_line < 1
1845
          || end_line < start_line || end_line > symtab->nlines)
1846
        {
1847
          return;
1848
        }
1849
 
1850
      line_number[0] = '\t';
1851
      line[0] = '\t';
1852
 
1853
      text_argv = client_data->source_argv;
1854
 
1855
      text_argv[3] = line_number;
1856
      text_argv[5] = line;
1857
 
1858
      if (fseek (client_data->fp, symtab->line_charpos[start_line - 1],
1859
                 SEEK_SET) < 0)
1860
        {
1861
          fclose(client_data->fp);
1862
          client_data->file_opened_p = -1;
1863
          return;
1864
        }
1865
 
1866
      for (; start_line < end_line; start_line++)
1867
        {
1868
          if (!fgets (line + 1, 9980, client_data->fp))
1869
            {
1870
              fclose(client_data->fp);
1871
              client_data->file_opened_p = -1;
1872
              return;
1873
            }
1874
 
1875
          client_data->widget_line_no++;
1876
 
1877
          sprintf (line_number + 1, "%d", start_line);
1878
 
1879
          if (found_carriage_return) {
1880
            char *p;
1881
 
1882
            p = strrchr(line, '\0') - 2;
1883
            if (*p == '\r') {
1884
              *p = '\n';
1885
              *(p + 1) = '\0';
1886
            } else {
1887
              found_carriage_return = 0;
1888
            }
1889
          }
1890
 
1891
          /* Run the command, then add an entry to the map array in
1892
             the caller's scope, if requested. */
1893
 
1894
          client_data->cmd.proc (client_data->cmd.clientData,
1895
                                 client_data->interp, 7, text_argv);
1896
 
1897
          if (*client_data->map_arr != '\0')
1898
            {
1899
 
1900
              Tcl_DStringAppend (&client_data->src_to_line_prefix,
1901
                                 line_number + 1, -1);
1902
 
1903
              /* FIXME: Convert to Tcl_SetVar2Ex when we move to 8.2.  This
1904
                 will allow us avoid converting widget_line_no into a string. */
1905
 
1906
            xasprintf (&buffer, "%d", client_data->widget_line_no);
1907
 
1908
              Tcl_SetVar2 (client_data->interp, client_data->map_arr,
1909
                           Tcl_DStringValue (&client_data->src_to_line_prefix),
1910
                           buffer, 0);
1911
            free(buffer);
1912
 
1913
              Tcl_DStringSetLength (&client_data->src_to_line_prefix, index_len);
1914
            }
1915
        }
1916
 
1917
    }
1918
  else if (!client_data->file_opened_p)
1919
    {
1920
      int fdes;
1921
      /* The file is not yet open, try to open it, then print the
1922
         first line.  If we fail, set FILE_OPEN_P to -1. */
1923
 
1924
      fdes = open_source_file (symtab);
1925
      if (fdes < 0)
1926
        {
1927
          client_data->file_opened_p = -1;
1928
        }
1929
      else
1930
        {
1931
          /* FIXME: Convert to a Tcl File Channel and read from there.
1932
             This will allow us to get the line endings and conversion
1933
             to UTF8 right automatically when we move to 8.2.
1934
             Need a Cygwin call to convert a file descriptor to the native
1935
             Windows handler to do this. */
1936
 
1937
          client_data->file_opened_p = 1;
1938
          client_data->fp = fdopen (fdes, FOPEN_RB);
1939
          clearerr (client_data->fp);
1940
 
1941
          if (symtab->line_charpos == 0)
1942
            find_source_lines (symtab, fdes);
1943
 
1944
          /* We are called with an actual load request, so call ourselves
1945
             to load the first line. */
1946
 
1947
          gdbtk_load_source (clientData, symtab, start_line, end_line);
1948
        }
1949
    }
1950
  else {
1951
    /* If we couldn't open the file, or got some prior error, just exit. */
1952
 
1953
    return;
1954
  }
1955
 
1956
}
1957
 
1958
 
1959
static CORE_ADDR
1960
gdbtk_load_asm (clientData, pc, di)
1961
     ClientData clientData;
1962
     CORE_ADDR pc;
1963
     struct disassemble_info *di;
1964
{
1965
  struct disassembly_client_data * client_data
1966
    = (struct disassembly_client_data *) clientData;
1967
  char **text_argv;
1968
  int i, pc_to_line_len, line_to_pc_len;
1969
  gdbtk_result new_result;
1970
  struct cleanup *old_chain = NULL;
1971
 
1972
  pc_to_line_len = Tcl_DStringLength (&client_data->pc_to_line_prefix);
1973
  line_to_pc_len = Tcl_DStringLength (&client_data->line_to_pc_prefix);
1974
 
1975
  text_argv = client_data->asm_argv;
1976
 
1977
  /* Preserve the current Tcl result object, print out what we need, and then
1978
     suck it out of the result, and replace... */
1979
 
1980
  old_chain = make_cleanup (gdbtk_restore_result_ptr, (void *) result_ptr);
1981
  result_ptr = &new_result;
1982
  result_ptr->obj_ptr = client_data->result_obj[0];
1983
  result_ptr->flags = GDBTK_TO_RESULT;
1984
 
1985
  /* Null out the three return objects we will use. */
1986
 
1987
  for (i = 0; i < 3; i++)
1988
    Tcl_SetObjLength (client_data->result_obj[i], 0);
1989
 
1990
  print_address_numeric (pc, 1, gdb_stdout);
1991
  gdb_flush (gdb_stdout);
1992
 
1993
  result_ptr->obj_ptr = client_data->result_obj[1];
1994
 
1995
  print_address_symbolic (pc, gdb_stdout, 1, "\t");
1996
  gdb_flush (gdb_stdout);
1997
 
1998
  result_ptr->obj_ptr = client_data->result_obj[2];
1999
  pc += (*tm_print_insn) (pc, di);
2000
  gdb_flush (gdb_stdout);
2001
 
2002
  client_data->widget_line_no++;
2003
 
2004
  text_argv[5] = Tcl_GetStringFromObj (client_data->result_obj[0], NULL);
2005
  text_argv[7] = Tcl_GetStringFromObj (client_data->result_obj[1], NULL);
2006
  text_argv[11] = Tcl_GetStringFromObj (client_data->result_obj[2], NULL);
2007
 
2008
  client_data->cmd.proc (client_data->cmd.clientData,
2009
                                     client_data->interp, 14, text_argv);
2010
 
2011
  if (*client_data->map_arr != '\0')
2012
    {
2013
      char *buffer;
2014
 
2015
      /* Run the command, then add an entry to the map array in
2016
         the caller's scope. */
2017
 
2018
      Tcl_DStringAppend (&client_data->pc_to_line_prefix, text_argv[5], -1);
2019
 
2020
      /* FIXME: Convert to Tcl_SetVar2Ex when we move to 8.2.  This
2021
         will allow us avoid converting widget_line_no into a string. */
2022
 
2023
      xasprintf (&buffer, "%d", client_data->widget_line_no);
2024
 
2025
      Tcl_SetVar2 (client_data->interp, client_data->map_arr,
2026
                   Tcl_DStringValue (&client_data->pc_to_line_prefix),
2027
                   buffer, 0);
2028
 
2029
      Tcl_DStringAppend (&client_data->line_to_pc_prefix, buffer, -1);
2030
 
2031
      Tcl_SetVar2 (client_data->interp, client_data->map_arr,
2032
                   Tcl_DStringValue (&client_data->line_to_pc_prefix),
2033
                   text_argv[5], 0);
2034
 
2035
      /* Restore the prefixes to their initial state. */
2036
 
2037
      Tcl_DStringSetLength (&client_data->pc_to_line_prefix, pc_to_line_len);
2038
      Tcl_DStringSetLength (&client_data->line_to_pc_prefix, line_to_pc_len);
2039
 
2040
      free(buffer);
2041
    }
2042
 
2043
  do_cleanups (old_chain);
2044
 
2045
  return pc;
2046
}
2047
 
2048
static void
2049
gdbtk_print_source (clientData, symtab, start_line, end_line)
2050
     ClientData clientData;
2051
     struct symtab *symtab;
2052
     int start_line;
2053
     int end_line;
2054
{
2055
  print_source_lines (symtab, start_line, end_line, 0);
2056
  gdb_flush (gdb_stdout);
2057
}
2058
 
2059
static CORE_ADDR
2060
gdbtk_print_asm (clientData, pc, di)
2061
     ClientData clientData;
2062
     CORE_ADDR pc;
2063
     struct disassemble_info *di;
2064
{
2065
  fputs_unfiltered ("    ", gdb_stdout);
2066
  print_address (pc, gdb_stdout);
2067
  fputs_unfiltered (":\t    ", gdb_stdout);
2068
  pc += (*tm_print_insn) (pc, di);
2069
  fputs_unfiltered ("\n", gdb_stdout);
2070
  gdb_flush (gdb_stdout);
2071
  return pc;
2072
}
2073
 
2074
static int
2075
gdb_disassemble_driver (low, high, mixed_source_and_assembly,
2076
                        clientData, print_source_fn, print_asm_fn)
2077
     CORE_ADDR low;
2078
     CORE_ADDR high;
2079
     int mixed_source_and_assembly;
2080
     ClientData clientData;
2081
     void (*print_source_fn) (ClientData, struct symtab *, int, int);
2082
     CORE_ADDR (*print_asm_fn) (ClientData, CORE_ADDR,
2083
                                struct disassemble_info *);
2084
{
2085
  CORE_ADDR pc;
2086
  static disassemble_info di;
2087
  static int di_initialized;
2088
 
2089
  if (! di_initialized)
2090
    {
2091
      INIT_DISASSEMBLE_INFO_NO_ARCH (di, gdb_stdout,
2092
                                     (fprintf_ftype) fprintf_unfiltered);
2093
      di.flavour = bfd_target_unknown_flavour;
2094
      di.memory_error_func = dis_asm_memory_error;
2095
      di.print_address_func = dis_asm_print_address;
2096
      di_initialized = 1;
2097
    }
2098
 
2099
  di.mach = TARGET_PRINT_INSN_INFO->mach;
2100
  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
2101
    di.endian = BFD_ENDIAN_BIG;
2102
  else
2103
    di.endian = BFD_ENDIAN_LITTLE;
2104
 
2105
  /* Set the architecture for multi-arch configurations. */
2106
  if (TARGET_ARCHITECTURE != NULL)
2107
    di.mach = TARGET_ARCHITECTURE->mach;
2108
 
2109
  /* If disassemble_from_exec == -1, then we use the following heuristic to
2110
     determine whether or not to do disassembly from target memory or from the
2111
     exec file:
2112
 
2113
     If we're debugging a local process, read target memory, instead of the
2114
     exec file.  This makes disassembly of functions in shared libs work
2115
     correctly.  Also, read target memory if we are debugging native threads.
2116
 
2117
     Else, we're debugging a remote process, and should disassemble from the
2118
     exec file for speed.  However, this is no good if the target modifies its
2119
     code (for relocation, or whatever).
2120
 
2121
     As an aside, it is fairly bogus that there is not a better way to
2122
     determine where to disassemble from.  There should be a target vector
2123
     entry for this or something.
2124
 
2125
   */
2126
 
2127
  if (disassemble_from_exec == -1)
2128
    {
2129
      if (strcmp (target_shortname, "child") == 0
2130
          || strcmp (target_shortname, "procfs") == 0
2131
          || strcmp (target_shortname, "vxprocess") == 0
2132
          || strstr (target_shortname, "threads") != NULL)
2133
        /* It's a child process, read inferior mem */
2134
        disassemble_from_exec = 0;
2135
      else
2136
        /* It's remote, read the exec file */
2137
        disassemble_from_exec = 1;
2138
    }
2139
 
2140
  if (disassemble_from_exec)
2141
    di.read_memory_func = gdbtk_dis_asm_read_memory;
2142
  else
2143
    di.read_memory_func = dis_asm_read_memory;
2144
 
2145
  /* If just doing straight assembly, all we need to do is disassemble
2146
     everything between low and high.  If doing mixed source/assembly, we've
2147
     got a totally different path to follow.  */
2148
 
2149
  if (mixed_source_and_assembly)
2150
    {                           /* Come here for mixed source/assembly */
2151
      /* The idea here is to present a source-O-centric view of a function to
2152
         the user.  This means that things are presented in source order, with
2153
         (possibly) out of order assembly immediately following.  */
2154
      struct symtab *symtab;
2155
      struct linetable_entry *le;
2156
      int nlines;
2157
      int newlines;
2158
      struct my_line_entry *mle;
2159
      struct symtab_and_line sal;
2160
      int i;
2161
      int out_of_order;
2162
      int next_line;
2163
 
2164
      /* Assume symtab is valid for whole PC range */
2165
      symtab = find_pc_symtab (low);
2166
 
2167
      if (!symtab || !symtab->linetable)
2168
        goto assembly_only;
2169
 
2170
      /* First, convert the linetable to a bunch of my_line_entry's.  */
2171
 
2172
      le = symtab->linetable->item;
2173
      nlines = symtab->linetable->nitems;
2174
 
2175
      if (nlines <= 0)
2176
        goto assembly_only;
2177
 
2178
      mle = (struct my_line_entry *) alloca (nlines *
2179
                                             sizeof (struct my_line_entry));
2180
 
2181
      out_of_order = 0;
2182
 
2183
      /* Copy linetable entries for this function into our data structure,
2184
         creating end_pc's and setting out_of_order as appropriate.  */
2185
 
2186
      /* First, skip all the preceding functions.  */
2187
 
2188
      for (i = 0; i < nlines - 1 && le[i].pc < low; i++) ;
2189
 
2190
      /* Now, copy all entries before the end of this function.  */
2191
 
2192
      newlines = 0;
2193
      for (; i < nlines - 1 && le[i].pc < high; i++)
2194
        {
2195
          if (le[i].line == le[i + 1].line
2196
              && le[i].pc == le[i + 1].pc)
2197
            continue;           /* Ignore duplicates */
2198
 
2199
          /* GCC sometimes emits line directives with a linenumber
2200
             of 0.  It does this to handle live range splitting.
2201
             This may be a bug, but we need to be able to handle it.
2202
             For now, use the previous instructions line number.
2203
             Since this is a bit of a hack anyway, we will just lose
2204
             if the bogus sline is the first line of the range.  For
2205
             functions, I have never seen this to be the case.  */
2206
 
2207
          if (le[i].line != 0)
2208
            {
2209
              mle[newlines].line = le[i].line;
2210
            }
2211
          else
2212
            {
2213
              if (newlines > 0)
2214
                mle[newlines].line = mle[newlines - 1].line;
2215
            }
2216
 
2217
          if (le[i].line > le[i + 1].line)
2218
            out_of_order = 1;
2219
          mle[newlines].start_pc = le[i].pc;
2220
          mle[newlines].end_pc = le[i + 1].pc;
2221
          newlines++;
2222
        }
2223
 
2224
      /* If we're on the last line, and it's part of the function, then we
2225
         need to get the end pc in a special way.  */
2226
 
2227
      if (i == nlines - 1
2228
          && le[i].pc < high)
2229
        {
2230
          mle[newlines].line = le[i].line;
2231
          mle[newlines].start_pc = le[i].pc;
2232
          sal = find_pc_line (le[i].pc, 0);
2233
          mle[newlines].end_pc = sal.end;
2234
          newlines++;
2235
        }
2236
 
2237
      /* Now, sort mle by line #s (and, then by addresses within lines). */
2238
 
2239
      if (out_of_order)
2240
        qsort (mle, newlines, sizeof (struct my_line_entry), compare_lines);
2241
 
2242
      /* Now, for each line entry, emit the specified lines (unless they have
2243
         been emitted before), followed by the assembly code for that line.  */
2244
 
2245
      next_line = 0;             /* Force out first line */
2246
      for (i = 0; i < newlines; i++)
2247
        {
2248
          /* Print out everything from next_line to the current line.  */
2249
 
2250
          if (mle[i].line >= next_line)
2251
            {
2252
              if (next_line != 0)
2253
                print_source_fn (clientData, symtab, next_line,
2254
                                 mle[i].line + 1);
2255
              else
2256
                print_source_fn (clientData, symtab, mle[i].line,
2257
                                 mle[i].line + 1);
2258
 
2259
              next_line = mle[i].line + 1;
2260
            }
2261
 
2262
          for (pc = mle[i].start_pc; pc < mle[i].end_pc; )
2263
            {
2264
              QUIT;
2265
              pc = print_asm_fn (clientData, pc, &di);
2266
            }
2267
        }
2268
    }
2269
  else
2270
    {
2271
    assembly_only:
2272
      for (pc = low; pc < high; )
2273
        {
2274
          QUIT;
2275
          pc = print_asm_fn (clientData, pc, &di);
2276
        }
2277
    }
2278
 
2279
  return TCL_OK;
2280
}
2281
 
2282
/* This is the memory_read_func for gdb_disassemble when we are
2283
   disassembling from the exec file. */
2284
 
2285
static int
2286
gdbtk_dis_asm_read_memory (memaddr, myaddr, len, info)
2287
     bfd_vma memaddr;
2288
     bfd_byte *myaddr;
2289
     unsigned int len;
2290
     disassemble_info *info;
2291
{
2292
  extern struct target_ops exec_ops;
2293
  int res;
2294
 
2295
  errno = 0;
2296
  res = xfer_memory (memaddr, myaddr, len, 0, 0, &exec_ops);
2297
 
2298
  if (res == len)
2299
    return 0;
2300
  else if (errno == 0)
2301
    return EIO;
2302
  else
2303
    return errno;
2304
}
2305
 
2306
/* This will be passed to qsort to sort the results of the disassembly */
2307
 
2308
static int
2309
compare_lines (mle1p, mle2p)
2310
     const PTR mle1p;
2311
     const PTR mle2p;
2312
{
2313
  struct my_line_entry *mle1, *mle2;
2314
  int val;
2315
 
2316
  mle1 = (struct my_line_entry *) mle1p;
2317
  mle2 = (struct my_line_entry *) mle2p;
2318
 
2319
  val = mle1->line - mle2->line;
2320
 
2321
  if (val != 0)
2322
    return val;
2323
 
2324
  return mle1->start_pc - mle2->start_pc;
2325
}
2326
 
2327
/* This implements the TCL command `gdb_loc',
2328
 
2329
 * Arguments:
2330
 *    ?symbol? The symbol or address to locate - defaults to pc
2331
 * Tcl Return:
2332
 *    a list consisting of the following:
2333
 *       basename, function name, filename, line number, address, current pc
2334
 */
2335
 
2336
static int
2337
gdb_loc (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
2338
{
2339
  char *filename;
2340
  struct symtab_and_line sal;
2341
  char *fname;
2342
  CORE_ADDR pc;
2343
 
2344
  if (objc == 1)
2345
    {
2346
      if (selected_frame && (selected_frame->pc != read_pc ()))
2347
        {
2348
          /* Note - this next line is not correct on all architectures.
2349
             For a graphical debugger we really want to highlight the
2350
             assembly line that called the next function on the stack.
2351
             Many architectures have the next instruction saved as the
2352
             pc on the stack, so what happens is the next instruction
2353
             is highlighted. FIXME */
2354
          pc = selected_frame->pc;
2355
          sal = find_pc_line (selected_frame->pc,
2356
                              selected_frame->next != NULL
2357
                              && !selected_frame->next->signal_handler_caller
2358
                              && !frame_in_dummy (selected_frame->next));
2359
        }
2360
      else
2361
        {
2362
          pc = read_pc ();
2363
          sal = find_pc_line (pc, 0);
2364
        }
2365
    }
2366
  else if (objc == 2)
2367
    {
2368
      struct symtabs_and_lines sals;
2369
      int nelts;
2370
 
2371
      sals = decode_line_spec (Tcl_GetStringFromObj (objv[1], NULL), 1);
2372
 
2373
      nelts = sals.nelts;
2374
      sal = sals.sals[0];
2375
      free (sals.sals);
2376
 
2377
      if (sals.nelts != 1)
2378
        {
2379
          Tcl_SetStringObj (result_ptr->obj_ptr, "Ambiguous line spec", -1);
2380
          return TCL_ERROR;
2381
        }
2382
      resolve_sal_pc (&sal);
2383
      pc = sal.pc;
2384
    }
2385
  else
2386
    {
2387
      Tcl_WrongNumArgs (interp, 1, objv, "?symbol?");
2388
      return TCL_ERROR;
2389
    }
2390
 
2391
  if (sal.symtab)
2392
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2393
                              Tcl_NewStringObj (sal.symtab->filename, -1));
2394
  else
2395
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2396
                              Tcl_NewStringObj ("", 0));
2397
 
2398
  fname = pc_function_name (pc);
2399
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2400
                            Tcl_NewStringObj (fname, -1));
2401
 
2402
  filename = symtab_to_filename (sal.symtab);
2403
  if (filename == NULL)
2404
    filename = "";
2405
 
2406
  /* file name */
2407
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2408
                            Tcl_NewStringObj (filename, -1));
2409
  /* line number */
2410
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2411
                            Tcl_NewIntObj (sal.line));
2412
  /* PC in current frame */
2413
  sprintf_append_element_to_obj (result_ptr->obj_ptr, "0x%s", paddr_nz (pc));
2414
  /* Real PC */
2415
  sprintf_append_element_to_obj (result_ptr->obj_ptr, "0x%s",
2416
                                 paddr_nz (stop_pc));
2417
 
2418
  /* shared library */
2419
#ifdef PC_SOLIB
2420
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2421
                            Tcl_NewStringObj (PC_SOLIB (pc), -1));
2422
#else
2423
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2424
                            Tcl_NewStringObj ("", -1));
2425
#endif
2426
  return TCL_OK;
2427
}
2428
 
2429
/* This implements the TCL command gdb_entry_point.  It returns the current
2430
   entry point address.  */
2431
 
2432
static int
2433
gdb_entry_point (clientData, interp, objc, objv)
2434
     ClientData clientData;
2435
     Tcl_Interp *interp;
2436
     int objc;
2437
     Tcl_Obj *CONST objv[];
2438
{
2439
  char *addrstr;
2440
 
2441
  /* If we have not yet loaded an exec file, then we have no
2442
     entry point, so return an empty string.*/
2443
  if ((int) current_target.to_stratum > (int) dummy_stratum)
2444
    {
2445
      addrstr = paddr_nz (entry_point_address ());
2446
      Tcl_SetStringObj (result_ptr->obj_ptr, addrstr, -1);
2447
    }
2448
  else
2449
    Tcl_SetStringObj (result_ptr->obj_ptr, "", -1);
2450
 
2451
  return TCL_OK;
2452
}
2453
 
2454
/* Covert hex to binary. Stolen from remote.c,
2455
   but added error handling */
2456
static int
2457
fromhex (int a)
2458
{
2459
  if (a >= '0' && a <= '9')
2460
    return a - '0';
2461
  else if (a >= 'a' && a <= 'f')
2462
    return a - 'a' + 10;
2463
  else if (a >= 'A' && a <= 'F')
2464
    return a - 'A' + 10;
2465
 
2466
  return -1;
2467
}
2468
 
2469
static int
2470
hex2bin (const char *hex, char *bin, int count)
2471
{
2472
  int i;
2473
  int m, n;
2474
 
2475
  for (i = 0; i < count; i++)
2476
    {
2477
      if (hex[0] == 0 || hex[1] == 0)
2478
        {
2479
          /* Hex string is short, or of uneven length.
2480
             Return the count that has been converted so far. */
2481
          return i;
2482
        }
2483
      m = fromhex (hex[0]);
2484
      n = fromhex (hex[1]);
2485
      if (m == -1 || n == -1)
2486
        return -1;
2487
      *bin++ = m * 16 + n;
2488
      hex += 2;
2489
    }
2490
 
2491
  return i;
2492
}
2493
 
2494
/* This implements the Tcl command 'gdb_set_mem', which
2495
 * sets some chunk of memory.
2496
 *
2497
 * Arguments:
2498
 *   gdb_set_mem addr hexstr len
2499
 *
2500
 *   addr:   address of data to set
2501
 *   hexstr: ascii string of data to set
2502
 *   len:    number of bytes of data to set
2503
 */
2504
static int
2505
gdb_set_mem (clientData, interp, objc, objv)
2506
     ClientData clientData;
2507
     Tcl_Interp *interp;
2508
     int objc;
2509
     Tcl_Obj *CONST objv[];
2510
{
2511
  CORE_ADDR addr;
2512
  char buf[128];
2513
  char *hexstr;
2514
  int len, size;
2515
 
2516
  if (objc != 4)
2517
    {
2518
      Tcl_WrongNumArgs (interp, 1, objv, "addr hex_data len");
2519
      return TCL_ERROR;
2520
    }
2521
 
2522
  /* Address to write */
2523
  addr = parse_and_eval_address (Tcl_GetStringFromObj (objv[1], NULL));
2524
 
2525
  /* String value to write: it's in hex */
2526
  hexstr = Tcl_GetStringFromObj (objv[2], NULL);
2527
  if (hexstr == NULL)
2528
    return TCL_ERROR;
2529
 
2530
  /* Length of buf */
2531
  if (Tcl_GetIntFromObj (interp, objv[3], &len) != TCL_OK)
2532
    return TCL_ERROR;
2533
 
2534
  /* Convert hexstr to binary and write */
2535
  if (hexstr[0] == '0' && hexstr[1] == 'x')
2536
    hexstr += 2;
2537
  size = hex2bin (hexstr, buf, strlen (hexstr));
2538
  if (size < 0)
2539
    {
2540
      /* Error in input */
2541
      char *res;
2542
 
2543
      xasprintf (&res, "Invalid hexadecimal input: \"0x%s\"", hexstr);
2544
      Tcl_SetObjResult (interp, Tcl_NewStringObj (res, -1));
2545
      free (res);
2546
      return TCL_ERROR;
2547
    }
2548
 
2549
  target_write_memory (addr, buf, len);
2550
  return TCL_OK;
2551
}
2552
 
2553
/* This implements the Tcl command 'gdb_get_mem', which
2554
 * dumps a block of memory
2555
 * Arguments:
2556
 *   gdb_get_mem addr form size nbytes bpr aschar
2557
 *
2558
 *   addr: address of data to dump
2559
 *   form: a char indicating format
2560
 *   size: size of each element; 1,2,4, or 8 bytes
2561
 *   nbytes: the number of bytes to read
2562
 *   bpr: bytes per row
2563
 *   aschar: if present, an ASCII dump of the row is included.  ASCHAR
2564
 *   used for unprintable characters.
2565
 *
2566
 * Return:
2567
 * a list of elements followed by an optional ASCII dump */
2568
 
2569
static int
2570
gdb_get_mem (clientData, interp, objc, objv)
2571
     ClientData clientData;
2572
     Tcl_Interp *interp;
2573
     int objc;
2574
     Tcl_Obj *CONST objv[];
2575
{
2576
  int size, asize, i, j, bc;
2577
  CORE_ADDR addr;
2578
  int nbytes, rnum, bpr;
2579
  long tmp;
2580
  char format, buff[128], aschar, *mbuf, *mptr, *cptr, *bptr;
2581
  struct type *val_type;
2582
 
2583
  if (objc < 6 || objc > 7)
2584
    {
2585
      Tcl_SetStringObj (result_ptr->obj_ptr,
2586
                        "addr format size bytes bytes_per_row ?ascii_char?",
2587
                        -1);
2588
      return TCL_ERROR;
2589
    }
2590
 
2591
  if (Tcl_GetIntFromObj (interp, objv[3], &size) != TCL_OK)
2592
    {
2593
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
2594
      return TCL_ERROR;
2595
    }
2596
  else if (size <= 0)
2597
    {
2598
      Tcl_SetStringObj (result_ptr->obj_ptr, "Invalid size, must be > 0", -1);
2599
      return TCL_ERROR;
2600
    }
2601
 
2602
  if (Tcl_GetIntFromObj (interp, objv[4], &nbytes) != TCL_OK)
2603
    {
2604
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
2605
      return TCL_ERROR;
2606
    }
2607
  else if (nbytes <= 0)
2608
    {
2609
      Tcl_SetStringObj (result_ptr->obj_ptr,
2610
                        "Invalid number of bytes, must be > 0",
2611
                        -1);
2612
      return TCL_ERROR;
2613
    }
2614
 
2615
  if (Tcl_GetIntFromObj (interp, objv[5], &bpr) != TCL_OK)
2616
    {
2617
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
2618
      return TCL_ERROR;
2619
    }
2620
  else if (bpr <= 0)
2621
    {
2622
      Tcl_SetStringObj (result_ptr->obj_ptr,
2623
                        "Invalid bytes per row, must be > 0", -1);
2624
      return TCL_ERROR;
2625
    }
2626
 
2627
  if (Tcl_GetLongFromObj (interp, objv[1], &tmp) != TCL_OK)
2628
    return TCL_OK;
2629
 
2630
  addr = (CORE_ADDR) tmp;
2631
 
2632
  format = *(Tcl_GetStringFromObj (objv[2], NULL));
2633
  mbuf = (char *) malloc (nbytes + 32);
2634
  if (!mbuf)
2635
    {
2636
      Tcl_SetStringObj (result_ptr->obj_ptr, "Out of memory.", -1);
2637
      return TCL_ERROR;
2638
    }
2639
 
2640
  memset (mbuf, 0, nbytes + 32);
2641
  mptr = cptr = mbuf;
2642
 
2643
  rnum = 0;
2644
  while (rnum < nbytes)
2645
    {
2646
      int error;
2647
      int num = target_read_memory_partial (addr + rnum, mbuf + rnum,
2648
                                            nbytes - rnum, &error);
2649
      if (num <= 0)
2650
        break;
2651
      rnum += num;
2652
    }
2653
 
2654
  if (objc == 7)
2655
    aschar = *(Tcl_GetStringFromObj (objv[6], NULL));
2656
  else
2657
    aschar = 0;
2658
 
2659
  switch (size)
2660
    {
2661
    case 1:
2662
      val_type = builtin_type_int8;
2663
      asize = 'b';
2664
      break;
2665
    case 2:
2666
      val_type = builtin_type_int16;
2667
      asize = 'h';
2668
      break;
2669
    case 4:
2670
      val_type = builtin_type_int32;
2671
      asize = 'w';
2672
      break;
2673
    case 8:
2674
      val_type = builtin_type_int64;
2675
      asize = 'g';
2676
      break;
2677
    default:
2678
      val_type = builtin_type_int8;
2679
      asize = 'b';
2680
    }
2681
 
2682
  bc = 0;                        /* count of bytes in a row */
2683
  bptr = &buff[0];               /* pointer for ascii dump */
2684
 
2685
  /* Build up the result as a list... */
2686
 
2687
  result_ptr->flags |= GDBTK_MAKES_LIST;
2688
 
2689
  for (i = 0; i < nbytes; i += size)
2690
    {
2691
      if (i >= rnum)
2692
        {
2693
          Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2694
                                    Tcl_NewStringObj ("N/A", 3));
2695
          if (aschar)
2696
            for (j = 0; j < size; j++)
2697
              *bptr++ = 'X';
2698
        }
2699
      else
2700
        {
2701
          print_scalar_formatted (mptr, val_type, format, asize, gdb_stdout);
2702
 
2703
          if (aschar)
2704
            {
2705
              for (j = 0; j < size; j++)
2706
                {
2707
                  *bptr = *cptr++;
2708
                  if (*bptr < 32 || *bptr > 126)
2709
                    *bptr = aschar;
2710
                  bptr++;
2711
                }
2712
            }
2713
        }
2714
 
2715
      mptr += size;
2716
      bc += size;
2717
 
2718
      if (aschar && (bc >= bpr))
2719
        {
2720
          /* end of row. Add it to the result and reset variables */
2721
          Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2722
                                    Tcl_NewStringObj (buff, bc));
2723
          bc = 0;
2724
          bptr = &buff[0];
2725
        }
2726
    }
2727
 
2728
  result_ptr->flags &= ~GDBTK_MAKES_LIST;
2729
 
2730
  free (mbuf);
2731
  return TCL_OK;
2732
}
2733
 
2734
 
2735
/* This implements the tcl command "gdb_loadfile"
2736
 * It loads a c source file into a text widget.
2737
 *
2738
 * Tcl Arguments:
2739
 *    widget: the name of the text widget to fill
2740
 *    filename: the name of the file to load
2741
 *    linenumbers: A boolean indicating whether or not to display line numbers.
2742
 * Tcl Result:
2743
 *
2744
 */
2745
 
2746
/* In this routine, we will build up a "line table", i.e. a
2747
 * table of bits showing which lines in the source file are executible.
2748
 * LTABLE_SIZE is the number of bytes to allocate for the line table.
2749
 *
2750
 * Its size limits the maximum number of lines
2751
 * in a file to 8 * LTABLE_SIZE.  This memory is freed after
2752
 * the file is loaded, so it is OK to make this very large.
2753
 * Additional memory will be allocated if needed. */
2754
#define LTABLE_SIZE 20000
2755
static int
2756
gdb_loadfile (ClientData clientData, Tcl_Interp *interp, int objc,
2757
              Tcl_Obj *CONST objv[])
2758
{
2759
  char *file, *widget;
2760
  int linenumbers, ln, lnum, ltable_size;
2761
  FILE *fp;
2762
  char *ltable;
2763
  struct symtab *symtab;
2764
  struct linetable_entry *le;
2765
  long mtime = 0;
2766
  struct stat st;
2767
  char line[10000], line_num_buf[18];
2768
  char *text_argv[9];
2769
  Tcl_CmdInfo text_cmd;
2770
 
2771
 
2772
  if (objc != 4)
2773
    {
2774
      Tcl_WrongNumArgs(interp, 1, objv, "widget filename linenumbers");
2775
      return TCL_ERROR;
2776
    }
2777
 
2778
  widget = Tcl_GetStringFromObj (objv[1], NULL);
2779
  if ( Tk_NameToWindow (interp, widget, Tk_MainWindow (interp)) == NULL)
2780
    {
2781
      return TCL_ERROR;
2782
    }
2783
 
2784
  if (!Tcl_GetCommandInfo (interp, widget, &text_cmd))
2785
    {
2786
      Tcl_SetStringObj (result_ptr->obj_ptr, "Can't get widget command info",
2787
                        -1);
2788
      return TCL_ERROR;
2789
    }
2790
 
2791
  file  = Tcl_GetStringFromObj (objv[2], NULL);
2792
  Tcl_GetBooleanFromObj (interp, objv[3], &linenumbers);
2793
 
2794
  symtab = full_lookup_symtab (file);
2795
  if (!symtab)
2796
    {
2797
      Tcl_SetStringObj ( result_ptr->obj_ptr, "File not found in symtab", -1);
2798
      return TCL_ERROR;
2799
    }
2800
 
2801
  file = symtab_to_filename ( symtab );
2802
  if ((fp = fopen ( file, "r" )) == NULL)
2803
    {
2804
      Tcl_SetStringObj ( result_ptr->obj_ptr, "Can't open file for reading",
2805
                         -1);
2806
      return TCL_ERROR;
2807
    }
2808
 
2809
  if (stat (file, &st) < 0)
2810
    {
2811
      catch_errors (perror_with_name_wrapper, "gdbtk: get time stamp", "",
2812
                    RETURN_MASK_ALL);
2813
      return TCL_ERROR;
2814
    }
2815
 
2816
  if (symtab && symtab->objfile && symtab->objfile->obfd)
2817
      mtime = bfd_get_mtime(symtab->objfile->obfd);
2818
  else if (exec_bfd)
2819
      mtime = bfd_get_mtime(exec_bfd);
2820
 
2821
  if (mtime && mtime < st.st_mtime)
2822
    {
2823
      gdbtk_ignorable_warning("file_times",\
2824
                              "Source file is more recent than executable.\n");
2825
    }
2826
 
2827
 
2828
  /* Source linenumbers don't appear to be in order, and a sort is */
2829
  /* too slow so the fastest solution is just to allocate a huge */
2830
  /* array and set the array entry for each linenumber */
2831
 
2832
  ltable_size = LTABLE_SIZE;
2833
  ltable = (char *)malloc (LTABLE_SIZE);
2834
  if (ltable == NULL)
2835
    {
2836
      Tcl_SetStringObj ( result_ptr->obj_ptr, "Out of memory.", -1);
2837
      fclose (fp);
2838
      return TCL_ERROR;
2839
    }
2840
 
2841
  memset (ltable, 0, LTABLE_SIZE);
2842
 
2843
  if (symtab->linetable && symtab->linetable->nitems)
2844
    {
2845
      le = symtab->linetable->item;
2846
      for (ln = symtab->linetable->nitems ;ln > 0; ln--, le++)
2847
        {
2848
          lnum = le->line >> 3;
2849
          if (lnum >= ltable_size)
2850
            {
2851
              char *new_ltable;
2852
              new_ltable = (char *)realloc (ltable, ltable_size*2);
2853
              memset (new_ltable + ltable_size, 0, ltable_size);
2854
              ltable_size *= 2;
2855
              if (new_ltable == NULL)
2856
                {
2857
                  Tcl_SetStringObj ( result_ptr->obj_ptr, "Out of memory.",
2858
                                     -1);
2859
                  free (ltable);
2860
                  fclose (fp);
2861
                  return TCL_ERROR;
2862
                }
2863
              ltable = new_ltable;
2864
            }
2865
          ltable[lnum] |= 1 << (le->line % 8);
2866
        }
2867
    }
2868
 
2869
  ln = 1;
2870
 
2871
  line[0] = '\t';
2872
  text_argv[0] = widget;
2873
  text_argv[1] = "insert";
2874
  text_argv[2] = "end";
2875
  text_argv[5] = line;
2876
  text_argv[6] = "source_tag";
2877
  text_argv[8] = NULL;
2878
 
2879
  if (linenumbers)
2880
    {
2881
      int found_carriage_return = 1;
2882
 
2883
      line_num_buf[1] = '\t';
2884
 
2885
      text_argv[3] = line_num_buf;
2886
 
2887
      while (fgets (line + 1, 9980, fp))
2888
        {
2889
          /* Look for DOS style \r\n endings, and if found,
2890
           * strip off the \r.  We assume (for the sake of
2891
           * speed) that ALL lines in the file have DOS endings,
2892
           * or none do.
2893
           */
2894
 
2895
          if (found_carriage_return)
2896
            {
2897
              char *p;
2898
 
2899
              p = strrchr(line, '\0') - 2;
2900
              if (*p == '\r') {
2901
                *p = '\n';
2902
                *(p + 1) = '\0';
2903
              } else {
2904
                found_carriage_return = 0;
2905
              }
2906
            }
2907
 
2908
          sprintf (line_num_buf+2, "%d", ln);
2909
          if (ltable[ln >> 3] & (1 << (ln % 8)))
2910
            {
2911
              line_num_buf[0] = '-';
2912
              text_argv[4] = "break_rgn_tag";
2913
            }
2914
          else
2915
            {
2916
              line_num_buf[0] = ' ';
2917
              text_argv[4] = "";
2918
            }
2919
 
2920
          text_cmd.proc(text_cmd.clientData, interp, 7, text_argv);
2921
          ln++;
2922
        }
2923
    }
2924
  else
2925
    {
2926
      int found_carriage_return = 1;
2927
 
2928
      while (fgets (line + 1, 9980, fp))
2929
        {
2930
          if (found_carriage_return) {
2931
            char *p;
2932
 
2933
            p = strrchr(line, '\0') - 2;
2934
            if (*p == '\r') {
2935
              *p = '\n';
2936
              *(p + 1) = '\0';
2937
            } else {
2938
              found_carriage_return = 0;
2939
            }
2940
          }
2941
 
2942
          if (ltable[ln >> 3] & (1 << (ln % 8)))
2943
            {
2944
              text_argv[3] = "- ";
2945
              text_argv[4] = "break_rgn_tag";
2946
            }
2947
          else
2948
            {
2949
              text_argv[3] = "  ";
2950
              text_argv[4] = "";
2951
            }
2952
 
2953
          text_cmd.proc(text_cmd.clientData, interp, 7, text_argv);
2954
          ln++;
2955
        }
2956
    }
2957
 
2958
  free (ltable);
2959
  fclose (fp);
2960
  return TCL_OK;
2961
}
2962
 
2963
/*
2964
 * This section contains a bunch of miscellaneous utility commands
2965
 */
2966
 
2967
/* This implements the tcl command gdb_path_conv
2968
 
2969
 * On Windows, it canonicalizes the pathname,
2970
 * On Unix, it is a no op.
2971
 *
2972
 * Arguments:
2973
 *    path
2974
 * Tcl Result:
2975
 *    The canonicalized path.
2976
 */
2977
 
2978
static int
2979
gdb_path_conv (clientData, interp, objc, objv)
2980
     ClientData clientData;
2981
     Tcl_Interp *interp;
2982
     int objc;
2983
     Tcl_Obj *CONST objv[];
2984
{
2985
  if (objc != 2)
2986
    {
2987
      Tcl_WrongNumArgs (interp, 1, objv, NULL);
2988
      return TCL_ERROR;
2989
    }
2990
 
2991
#ifdef __CYGWIN__
2992
  {
2993
    char pathname[256], *ptr;
2994
 
2995
    cygwin32_conv_to_full_win32_path (Tcl_GetStringFromObj (objv[1], NULL),
2996
                                      pathname);
2997
    for (ptr = pathname; *ptr; ptr++)
2998
      {
2999
        if (*ptr == '\\')
3000
          *ptr = '/';
3001
      }
3002
    Tcl_SetStringObj (result_ptr->obj_ptr, pathname, -1);
3003
  }
3004
#else
3005
  Tcl_SetStringObj (result_ptr->obj_ptr, Tcl_GetStringFromObj (objv[1], NULL),
3006
                    -1);
3007
#endif
3008
 
3009
  return TCL_OK;
3010
}
3011
 
3012
/*
3013
 * This section has utility routines that are not Tcl commands.
3014
 */
3015
 
3016
static int
3017
perror_with_name_wrapper (args)
3018
     PTR args;
3019
{
3020
  perror_with_name (args);
3021
  return 1;
3022
}
3023
 
3024
/* The lookup_symtab() in symtab.c doesn't work correctly */
3025
/* It will not work will full pathnames and if multiple */
3026
/* source files have the same basename, it will return */
3027
/* the first one instead of the correct one. */
3028
/* symtab->fullname will be NULL if the file is not available. */
3029
 
3030
struct symtab *
3031
full_lookup_symtab (file)
3032
     char *file;
3033
{
3034
  struct symtab *st;
3035
  struct objfile *objfile;
3036
  char *bfile, *fullname;
3037
  struct partial_symtab *pt;
3038
 
3039
  if (!file)
3040
    return NULL;
3041
 
3042
  /* first try a direct lookup */
3043
  st = lookup_symtab (file);
3044
  if (st)
3045
    {
3046
      if (!st->fullname)
3047
        symtab_to_filename (st);
3048
      return st;
3049
    }
3050
 
3051
  /* if the direct approach failed, try */
3052
  /* looking up the basename and checking */
3053
  /* all matches with the fullname */
3054
  bfile = basename (file);
3055
  ALL_SYMTABS (objfile, st)
3056
  {
3057
    if (!strcmp (bfile, basename (st->filename)))
3058
      {
3059
        if (!st->fullname)
3060
          fullname = symtab_to_filename (st);
3061
        else
3062
          fullname = st->fullname;
3063
 
3064
        if (!strcmp (file, fullname))
3065
          return st;
3066
      }
3067
  }
3068
 
3069
  /* still no luck?  look at psymtabs */
3070
  ALL_PSYMTABS (objfile, pt)
3071
  {
3072
    if (!strcmp (bfile, basename (pt->filename)))
3073
      {
3074
        st = PSYMTAB_TO_SYMTAB (pt);
3075
        if (st)
3076
          {
3077
            fullname = symtab_to_filename (st);
3078
            if (!strcmp (file, fullname))
3079
              return st;
3080
          }
3081
      }
3082
  }
3083
  return NULL;
3084
}
3085
 
3086
/* Look for the function that contains PC and return the source
3087
   (demangled) name for this function.
3088
 
3089
   If no symbol is found, it returns an empty string. In either
3090
   case, memory is owned by gdb. Do not attempt to free it. */
3091
char *
3092
pc_function_name (pc)
3093
     CORE_ADDR pc;
3094
{
3095
  struct symbol *sym;
3096
  char *funcname = NULL;
3097
 
3098
  /* First lookup the address in the symbol table... */
3099
  sym = find_pc_function (pc);
3100
  if (sym != NULL)
3101
    funcname = GDBTK_SYMBOL_SOURCE_NAME (sym);
3102
  else
3103
    {
3104
      /* ... if that fails, look it up in the minimal symbols. */
3105
      struct minimal_symbol *msym = NULL;
3106
 
3107
      msym = lookup_minimal_symbol_by_pc (pc);
3108
      if (msym != NULL)
3109
        funcname = GDBTK_SYMBOL_SOURCE_NAME (msym);
3110
    }
3111
 
3112
  if (funcname == NULL)
3113
    funcname = "";
3114
 
3115
  return funcname;
3116
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.