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