#include "defs.h"
#include "target.h"
#include "frame.h"
#include "value.h"
#include "mi-cmds.h"
#include "ui-out.h"
#include "varobj.h"
#include "wrapper.h"
#include "interpreter.h"
#include "symtab.h"
#include "symtab.h"
extern void select_frame_command_wrapper (char *, int);
extern void mi_report_var_creation (struct ui_out *uiout, struct varobj *var);
void mi_interp_stack_changed_hook (void);
void mi_interp_frame_changed_hook (int new_frame_number);
void mi_interp_context_hook (int thread_id);
extern struct gdb_interpreter *mi_interp;
void mi_print_frame_more_info (struct ui_out *uiout,
struct symtab_and_line *sal,
struct frame_info *fi);
static void list_args_or_locals (int locals, int values,
struct frame_info *fi,
int all_blocks,
int create_varobj);
static void print_syms_for_block (struct block *block,
struct frame_info *fi,
struct ui_stream *stb,
int locals,
int values,
int create_varobj);
enum mi_cmd_result
mi_cmd_stack_list_frames (char *command, char **argv, int argc)
{
int frame_low;
int frame_high;
int i;
struct frame_info *fi;
if (!target_has_stack)
error ("mi_cmd_stack_list_frames: No stack.");
if (argc > 2 || argc == 1)
error ("mi_cmd_stack_list_frames: Usage: [FRAME_LOW FRAME_HIGH]");
if (argc == 2)
{
frame_low = atoi (argv[0]);
frame_high = atoi (argv[1]);
}
else
{
frame_low = -1;
frame_high = -1;
}
for (i = 0, fi = get_current_frame ();
fi && i < frame_low;
i++, fi = get_prev_frame (fi));
if (fi == NULL)
error ("mi_cmd_stack_list_frames: Not enough frames in stack.");
ui_out_list_begin (uiout, "stack");
for (;
fi && (i <= frame_high || frame_high == -1);
i++, fi = get_prev_frame (fi))
{
QUIT;
print_frame_info (fi ,
i ,
LOC_AND_ADDRESS ,
0 );
}
ui_out_list_end (uiout);
if (i < frame_high)
error ("mi_cmd_stack_list_frames: Not enough frames in stack.");
return MI_CMD_DONE;
}
void
mi_print_frame_more_info (struct ui_out *uiout,
struct symtab_and_line *sal,
struct frame_info *fi)
{
if (sal && sal->symtab && sal->symtab->dirname)
ui_out_field_string (uiout, "dir", sal->symtab->dirname);
}
enum mi_cmd_result
mi_cmd_stack_info_depth (char *command, char **argv, int argc)
{
int frame_high;
int i;
struct frame_info *fi;
if (!target_has_stack)
error ("mi_cmd_stack_info_depth: No stack.");
if (argc > 1)
error ("mi_cmd_stack_info_depth: Usage: [MAX_DEPTH]");
if (argc == 1)
frame_high = atoi (argv[0]);
else
frame_high = -1;
#ifdef FAST_COUNT_STACK_DEPTH
if (!FAST_COUNT_STACK_DEPTH (&i))
#endif
{
for (i = 0, fi = get_current_frame ();
fi && (i < frame_high || frame_high == -1);
i++, fi = get_prev_frame (fi))
QUIT;
}
ui_out_field_int (uiout, "depth", i);
return MI_CMD_DONE;
}
enum mi_cmd_result
mi_cmd_stack_list_locals (char *command, char **argv, int argc)
{
int values;
int all_blocks;
int create_varobj;
if (argc < 1 || argc > 2)
error ("mi_cmd_stack_list_locals: Usage: PRINT_VALUES [ALL_BLOCKS]");
values = atoi (argv[0]);
create_varobj = (values == 2);
if (argc >= 2)
all_blocks = atoi (argv[1]);
else
all_blocks = 0;
list_args_or_locals (1, values, selected_frame,
all_blocks, create_varobj);
return MI_CMD_DONE;
}
enum mi_cmd_result
mi_cmd_stack_list_args (char *command, char **argv, int argc)
{
int frame_low;
int frame_high;
int i;
int values;
int create_varobj;
struct frame_info *fi;
if (argc < 1 || argc > 3 || argc == 2)
error ("mi_cmd_stack_list_args: Usage: PRINT_VALUES [FRAME_LOW FRAME_HIGH]");
if (argc == 3)
{
frame_low = atoi (argv[1]);
frame_high = atoi (argv[2]);
}
else
{
frame_low = -1;
frame_high = -1;
}
values = atoi (argv[0]);
create_varobj = (values == 2);
for (i = 0, fi = get_current_frame ();
fi && i < frame_low;
i++, fi = get_prev_frame (fi));
if (fi == NULL)
error ("mi_cmd_stack_list_args: Not enough frames in stack.");
ui_out_list_begin (uiout, "stack-args");
for (;
fi && (i <= frame_high || frame_high == -1);
i++, fi = get_prev_frame (fi))
{
QUIT;
ui_out_tuple_begin (uiout, "frame");
ui_out_field_int (uiout, "level", i);
list_args_or_locals (0, values, fi, 0, create_varobj);
ui_out_tuple_end (uiout);
}
ui_out_list_end (uiout);
if (i < frame_high)
error ("mi_cmd_stack_list_args: Not enough frames in stack.");
return MI_CMD_DONE;
}
static void
list_args_or_locals (int locals, int values, struct frame_info *fi,
int all_blocks, int create_varobj)
{
struct block *block = NULL;
int i, nsyms;
static struct ui_stream *stb = NULL;
stb = ui_out_stream_new (uiout);
ui_out_list_begin (uiout, locals ? "locals" : "args");
if (all_blocks)
{
CORE_ADDR fstart;
CORE_ADDR endaddr;
int index;
int nblocks;
struct blockvector *bv;
fstart = get_pc_function_start (get_frame_pc (fi));
if (fstart == 0)
{
fstart = fi->pc;
}
bv = blockvector_for_pc (fstart, &index);
if (bv == NULL)
{
error ("list_args_or_locals: Couldn't find block vector for pc %ux.",
fstart);
}
nblocks = BLOCKVECTOR_NBLOCKS (bv);
block = BLOCKVECTOR_BLOCK (bv, index);
endaddr = BLOCK_END (block);
while (BLOCK_END (block) <= endaddr)
{
print_syms_for_block (block, fi, stb, locals,
values, create_varobj);
index++;
if (index == nblocks)
break;
block = BLOCKVECTOR_BLOCK (bv, index);
}
}
else
{
block = get_frame_block (fi, 0);
while (block != 0)
{
print_syms_for_block (block, fi, stb, locals, values, create_varobj);
if (BLOCK_FUNCTION (block))
break;
else
block = BLOCK_SUPERBLOCK (block);
}
}
ui_out_list_end (uiout);
ui_out_stream_delete (stb);
}
static void
print_syms_for_block (struct block *block,
struct frame_info *fi,
struct ui_stream *stb,
int locals,
int values,
int create_varobj)
{
int nsyms;
int print_me;
struct symbol *sym;
int i;
struct ui_stream *error_stb;
struct cleanup *old_chain;
nsyms = BLOCK_NSYMS (block);
if (nsyms == 0)
return;
error_stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (error_stb);
ALL_BLOCK_SYMBOLS (block, i, sym)
{
print_me = 0;
switch (SYMBOL_CLASS (sym))
{
default:
case LOC_UNDEF:
case LOC_CONST:
case LOC_TYPEDEF:
case LOC_LABEL:
case LOC_BLOCK:
case LOC_CONST_BYTES:
case LOC_UNRESOLVED:
case LOC_OPTIMIZED_OUT:
print_me = 0;
break;
case LOC_ARG:
case LOC_REF_ARG:
case LOC_REGPARM:
case LOC_REGPARM_ADDR:
case LOC_LOCAL_ARG:
case LOC_BASEREG_ARG:
if (!locals)
print_me = 1;
break;
case LOC_LOCAL:
case LOC_BASEREG:
case LOC_STATIC:
case LOC_REGISTER:
if (locals)
print_me = 1;
break;
}
if (print_me)
{
struct symbol *sym2;
if (!create_varobj && !values)
{
ui_out_list_begin (uiout, NULL);
ui_out_field_string (uiout, "name", SYMBOL_NAME (sym));
ui_out_list_end (uiout);
continue;
}
if (!locals)
sym2 = lookup_symbol (SYMBOL_NAME (sym),
block, VAR_NAMESPACE,
(int *) NULL,
(struct symtab **) NULL);
else
sym2 = sym;
if (create_varobj)
{
struct varobj *new_var;
new_var = varobj_create (varobj_gen_name (),
SYMBOL_NAME (sym2),
fi->frame,
block,
USE_BLOCK_IN_FRAME);
if (new_var == NULL)
continue;
ui_out_list_begin (uiout, "varobj");
ui_out_field_string (uiout, "exp", SYMBOL_NAME (sym));
if (values)
{
if (new_var != NULL)
{
char *value_str;
struct ui_file *save_stderr;
save_stderr = gdb_stderr;
gdb_stderr = error_stb->stream;
if (gdb_varobj_get_value (new_var, &value_str))
{
ui_out_field_string (uiout, "value", value_str);
}
else
{
ui_out_field_stream (uiout, "value",
error_stb);
}
gdb_stderr = save_stderr;
}
else
ui_out_field_skip (uiout, "value");
}
mi_report_var_creation (uiout, new_var);
}
else
{
ui_out_list_begin (uiout, NULL);
ui_out_field_string (uiout, "name", SYMBOL_NAME (sym));
print_variable_value (sym2, fi, stb->stream);
ui_out_field_stream (uiout, "value", stb);
}
ui_out_list_end (uiout);
}
}
do_cleanups (old_chain);
}
enum mi_cmd_result
mi_cmd_stack_select_frame (char *command, char **argv, int argc)
{
if (!target_has_stack)
error ("mi_cmd_stack_select_frame: No stack.");
if (argc > 1)
error ("mi_cmd_stack_select_frame: Usage: [FRAME_SPEC]");
if (argc == 0)
select_frame_command_wrapper (0, 1 );
else
select_frame_command_wrapper (argv[0], 1 );
return MI_CMD_DONE;
}
void
mi_interp_stack_changed_hook (void)
{
struct ui_out *saved_ui_out = uiout;
struct mi_out *tmp_mi_out;
uiout = mi_interp->interpreter_out;
ui_out_list_begin (uiout, "MI_HOOK_RESULT");
ui_out_field_string (uiout, "HOOK_TYPE", "stack_changed");
ui_out_list_end (uiout);
uiout = saved_ui_out;
}
void
mi_interp_frame_changed_hook (int new_frame_number)
{
struct ui_out *saved_ui_out = uiout;
struct mi_out *tmp_mi_out;
uiout = mi_interp->interpreter_out;
ui_out_list_begin (uiout, "MI_HOOK_RESULT");
ui_out_field_string (uiout, "HOOK_TYPE", "frame_changed");
ui_out_field_int (uiout, "frame", new_frame_number);
ui_out_list_end (uiout);
uiout = saved_ui_out;
}
void
mi_interp_context_hook (int thread_id)
{
struct ui_out *saved_ui_out = uiout;
struct mi_out *tmp_mi_out;
uiout = mi_interp->interpreter_out;
ui_out_list_begin (uiout, "MI_HOOK_RESULT");
ui_out_field_string (uiout, "HOOK_TYPE", "thread_changed");
ui_out_field_int (uiout, "thread", thread_id);
ui_out_list_end (uiout);
uiout = saved_ui_out;
}