--- gdb-6.8/gdb/cp-valprint.c 2008-01-01 23:53:09.000000000 +0100 +++ gdb-6.8-patched/gdb/cp-valprint.c 2008-04-22 11:37:25.000000000 +0200 @@ -36,6 +36,10 @@ #include "valprint.h" #include "cp-support.h" #include "language.h" +#include "block.h" +#include "gdbcore.h" +#include "value.h" +#include "expression.h" /* Controls printing of vtbl's */ int vtblprint; @@ -70,6 +74,36 @@ value); } +/* Controls printing of STL containers */ +int stlprint; +static void +show_stlprint (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +Printing of STL containers is %s.\n"), + value); +} + +int stlprintcompatible; +static void +show_stlprintcompatible (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +Compatible printing of STL containers is %s.\n"), + value); +} + +int stllimit; +static void +show_stllimit (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +Maximum elements of STL containers is set to %s.\n"), (stllimit == 0 || stllimit == (unsigned int)-1) ? "unlimited" : value); +} + static struct obstack dont_print_vb_obstack; static struct obstack dont_print_statmem_obstack; @@ -148,6 +182,494 @@ DONT_PRINT is an array of baseclass types that we should not print, or zero if called from top level. */ +int +get_stl_inner_type (struct type *type, char *inner_type_name) +{ + int level = 1; + char *pname = type->main_type->name; + + while (*pname && *pname != '<') pname++; + if (*pname == 0) + { + // This is not a template ! + *inner_type_name = 0; + return 0; + } + + pname++; + + while (!(level == 1 && *pname == ',')) + { + if (*pname == '<') level++; + else if (*pname == '>') level--; + if (!(level == 1 && *pname == ',')) *inner_type_name++ = *pname++; + } + *inner_type_name = 0; + + return 1; +} + +int +get_stl_inner_type_pair (struct type *type, char *inner_type_key, char *inner_type_value) +{ + int level = 1; + char *pname = type->main_type->name; + + while (*pname && *pname != '<') pname++; + if (*pname == 0) + { + // This is not a template ! + *inner_type_key = 0; + *inner_type_value = 0; + return 0; + } + + pname++; + + while (!(level == 1 && *pname == ',')) + { + if (*pname == '<') level++; + else if (*pname == '>') level--; + if (!(level == 1 && *pname == ',')) *inner_type_key++ = *pname++; + } + *inner_type_key = 0; + + if (*pname == ',') + { + pname++; + while (!(level == 1 && *pname == ',')) + { + if (*pname == '<') level++; + else if (*pname == '>') level--; + if (!(level == 1 && *pname == ',')) *inner_type_value++ = *pname++; + } + *inner_type_value = 0; + } + + return 1; +} + +struct type * +cp_get_type(char * name, struct block * block) +{ + struct type *type; + struct type *ptr_type; + char *rname = (char *)malloc(strlen(name) + 1); + char *old = rname; + int nbPtrs = 0; + + strcpy(rname, name); + if (!strncmp(rname, "const ", 6)) rname += 6; + while (rname[strlen(rname) - 1] == '*') + { + nbPtrs++; + rname[strlen(rname) - 1] = 0; + } + + while (rname[strlen(rname) - 1] == ' ') + { + rname[strlen(rname) - 1] = 0; + } + + type = lookup_typename(rname, block, 1); + while (nbPtrs--) + { + ptr_type = NULL; + make_pointer_type(type, &ptr_type); + type = ptr_type; + } + + free(old); + return type; +} + +void +cp_print_stl_vector(struct type *type, CORE_ADDR address, + struct ui_file *stream, int format, int recurse, + enum val_prettyprint pretty) +{ + char *inner_name; + CORE_ADDR pc; + struct frame_info *current_frame; + struct type *void_type; + struct type *inner_type; + struct block *block; + int ptr_size; + unsigned int idx; + CORE_ADDR begin; + CORE_ADDR end; + gdb_byte *b; + + inner_name = (char *)malloc(strlen(type->main_type->name) + 1); + + if (get_stl_inner_type(type, inner_name)) + { + if (!stlprintcompatible) fprintf_filtered (stream, "vector<%s>", inner_name); + fprintf_filtered (stream, "{"); + if (pretty) fprintf_filtered (stream, "\n"); + current_frame = get_current_frame (); + pc = get_frame_address_in_block (current_frame); + block = block_for_pc (pc); + inner_type = cp_get_type (inner_name, block); + void_type = cp_get_type("void *", block); + ptr_size = TYPE_LENGTH(void_type); + + if (inner_type == NULL) + { + if (pretty) print_spaces_filtered (2 + 2 * recurse, stream); + fprintf_filtered (stream, " // no information for type %s\n", inner_name); + } + else + { + idx = 0; + begin = (CORE_ADDR)read_memory_integer (address, ptr_size); + end = (CORE_ADDR)read_memory_integer (address + ptr_size, ptr_size); + b = (gdb_byte *)malloc(TYPE_LENGTH(inner_type)); + while (begin != end) + { + if (idx >= stllimit) + { + fprintf_filtered (stream, "..."); + break; + } + if (pretty) print_spaces_filtered (2 + 2 * recurse, stream); + if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx++); + read_memory(begin, b, TYPE_LENGTH(inner_type)); + c_val_print(inner_type, b, 0, begin, stream, format, 0, recurse + 1, pretty); + begin += TYPE_LENGTH(inner_type); + if (begin != end) fprintf_filtered(stream, ", "); + if (pretty) + { + fprintf_filtered(stream, "\n"); + } + } + free(b); + } + if (pretty) print_spaces_filtered (2 * recurse, stream); + fprintf_filtered (stream, "}"); + if (recurse == 0) fprintf_filtered (stream, "\n"); + } + + free(inner_name); +} + +void +cp_print_stl_list(struct type *type, CORE_ADDR address, + struct ui_file *stream, int format, int recurse, + enum val_prettyprint pretty) +{ + char *inner_name; + CORE_ADDR pc; + CORE_ADDR node; + CORE_ADDR data_ptr; + struct frame_info *current_frame; + struct type *inner_type; + struct type *void_type; + struct block *block; + int ptr_size; + unsigned int idx; + gdb_byte *b; + + inner_name = (char *)malloc(strlen(type->main_type->name) + 1); + + if (get_stl_inner_type(type, inner_name)) + { + if (!stlprintcompatible) fprintf_filtered (stream, "list<%s>", inner_name); + fprintf_filtered (stream, "{"); + if (pretty) fprintf_filtered (stream, "\n"); + current_frame = get_current_frame (); + pc = get_frame_address_in_block (current_frame); + block = block_for_pc (pc); + inner_type = cp_get_type (inner_name, block); + void_type = cp_get_type("void *", block); + ptr_size = TYPE_LENGTH(void_type); + + if (inner_type == NULL) + { + if (pretty) print_spaces_filtered (2 + 2 * recurse, stream); + fprintf_filtered (stream, " // no information for type %s\n", inner_name); + } + else + { + idx = 0; + node = (CORE_ADDR)read_memory_integer (address, ptr_size); + b = (gdb_byte *)malloc(TYPE_LENGTH(inner_type)); + do + { + if (idx >= stllimit) + { + fprintf_filtered (stream, "..."); + break; + } + data_ptr = (CORE_ADDR)(node + ptr_size * 2); + if (pretty) print_spaces_filtered (2 + 2 * recurse, stream); + if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx++); + read_memory(data_ptr, b, TYPE_LENGTH(inner_type)); + c_val_print(inner_type, b, 0, data_ptr, stream, format, 0, recurse + 1, pretty); + node = (CORE_ADDR)read_memory_integer (node, ptr_size); + if (node != address) fprintf_filtered(stream, ", "); + if (pretty) + { + fprintf_filtered(stream, "\n"); + } + } while (node != address); + free(b); + } + if (pretty) print_spaces_filtered (2 * recurse, stream); + fprintf_filtered (stream, "}"); + if (recurse == 0) fprintf_filtered (stream, "\n"); + } + + free(inner_name); +} + +#define TREE_PARENT(A) ((CORE_ADDR)read_memory_integer ((A) + 1 * ptr_size, ptr_size)) +#define TREE_LEFT(A) ((CORE_ADDR)read_memory_integer ((A) + 2 * ptr_size, ptr_size)) +#define TREE_RIGHT(A) ((CORE_ADDR)read_memory_integer ((A) + 3 * ptr_size, ptr_size)) + +void +cp_print_stl_set(struct type *type, CORE_ADDR address, + struct ui_file *stream, int format, int recurse, + enum val_prettyprint pretty) +{ + char *inner_name; + CORE_ADDR pc; + CORE_ADDR node; + CORE_ADDR left; + CORE_ADDR tmp_node; + CORE_ADDR data_ptr; + struct frame_info *current_frame; + struct type *inner_type; + struct type *void_type; + struct block *block; + int ptr_size; + unsigned int idx; + int count; + gdb_byte *b; + + inner_name = (char *)malloc(strlen(type->main_type->name) + 1); + + if (get_stl_inner_type(type, inner_name)) + { + if (!stlprintcompatible) fprintf_filtered (stream, "set<%s>", inner_name); + fprintf_filtered (stream, "{"); + if (pretty) fprintf_filtered (stream, "\n"); + current_frame = get_current_frame (); + pc = get_frame_address_in_block (current_frame); + block = block_for_pc (pc); + inner_type = cp_get_type (inner_name, block); + void_type = cp_get_type("void *", block); + ptr_size = TYPE_LENGTH(void_type); + + if (inner_type == NULL) + { + if (pretty) print_spaces_filtered (2 + 2 * recurse, stream); + fprintf_filtered (stream, " // no information for type %s\n", inner_name); + } + else + { + b = (gdb_byte *)malloc(TYPE_LENGTH(inner_type)); + node = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size); + count = (int)read_memory_integer(address + 5 * ptr_size, ptr_size); + for (idx=0; idx= stllimit) + { + fprintf_filtered (stream, "..."); + break; + } + data_ptr = (CORE_ADDR)(node + ptr_size * 4); + if (pretty) print_spaces_filtered (2 + 2 * recurse, stream); + if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx); + read_memory(data_ptr, b, TYPE_LENGTH(inner_type)); + c_val_print(inner_type, b, 0, data_ptr, stream, format, 0, recurse + 1, pretty); + + if (TREE_RIGHT(node) != 0) + { + node = TREE_RIGHT(node); + while ((left = TREE_LEFT(node))) + { + node = left; + } + } + else + { + tmp_node = TREE_PARENT(node); + while (node == TREE_RIGHT(node)) + { + node = tmp_node; + tmp_node = TREE_PARENT(node); + } + if (TREE_RIGHT(node) != tmp_node) + { + node = tmp_node; + } + } + + if (idx != count - 1) fprintf_filtered(stream, ", "); + if (pretty) + { + fprintf_filtered(stream, "\n"); + } + } + free(b); + } + if (pretty) print_spaces_filtered (2 * recurse, stream); + fprintf_filtered (stream, "}"); + if (recurse == 0) fprintf_filtered (stream, "\n"); + } + + free(inner_name); +} + +void +cp_print_stl_map(struct type *type, CORE_ADDR address, + struct ui_file *stream, int format, int recurse, + enum val_prettyprint pretty) +{ + char *inner_key; + char *inner_value; + CORE_ADDR pc; + CORE_ADDR node; + CORE_ADDR left; + CORE_ADDR tmp_node; + CORE_ADDR data_ptr; + struct frame_info *current_frame; + struct type *inner_type_key; + struct type *inner_type_value; + struct type *void_type; + struct block *block; + int ptr_size; + unsigned int idx; + int count; + gdb_byte *b_key; + gdb_byte *b_value; + + inner_key = (char *)malloc(strlen(type->main_type->name) + 1); + inner_value = (char *)malloc(strlen(type->main_type->name) + 1); + + if (get_stl_inner_type_pair(type, inner_key, inner_value)) + { + if (!stlprintcompatible) fprintf_filtered (stream, "map<%s, %s>", inner_key, inner_value); + fprintf_filtered (stream, "{"); + if (pretty) fprintf_filtered (stream, "\n"); + current_frame = get_current_frame (); + pc = get_frame_address_in_block (current_frame); + block = block_for_pc (pc); + inner_type_key = cp_get_type (inner_key, block); + inner_type_value = cp_get_type (inner_value, block); + void_type = cp_get_type("void *", block); + ptr_size = TYPE_LENGTH(void_type); + + if (inner_type_key == NULL || inner_type_value == NULL) + { + if (pretty) print_spaces_filtered (2 + 2 * recurse, stream); + fprintf_filtered (stream, " // no information for type std::pair<%s, %s>\n", inner_key, inner_value); + } + else + { + b_key = (gdb_byte *)malloc(TYPE_LENGTH(inner_type_key)); + b_value = (gdb_byte *)malloc(TYPE_LENGTH(inner_type_value)); + node = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size); + count = (int)read_memory_integer(address + 5 * ptr_size, ptr_size); + for (idx=0; idx= stllimit) + { + fprintf_filtered (stream, "..."); + break; + } + data_ptr = (CORE_ADDR)(node + ptr_size * 4); + read_memory(data_ptr, b_key, TYPE_LENGTH(inner_type_key)); + read_memory(data_ptr + ptr_size, b_value, TYPE_LENGTH(inner_type_value)); + + if (pretty) print_spaces_filtered (2 + 2 * recurse, stream); + if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx); + fprintf_filtered (stream, "{"); + if (pretty) fprintf_filtered(stream, "\n"); + + if (pretty) print_spaces_filtered (4 + 2 * recurse, stream); + if (!stlprintcompatible) + { + fprintf_filtered(stream, "key "); + if (pretty) fprintf_filtered(stream, " "); + fprintf_filtered(stream, "= "); + } + c_val_print(inner_type_key, b_key, 0, data_ptr, stream, format, 0, recurse + 3, pretty); + if (pretty) fprintf_filtered(stream, ",\n"); else fprintf_filtered(stream, ", "); + if (pretty) print_spaces_filtered (4 + 2 * recurse, stream); + if (!stlprintcompatible) + { + fprintf_filtered(stream, "value = "); + } + c_val_print(inner_type_value, b_value, 0, data_ptr, stream, format, 0, recurse + 3, pretty); + if (pretty) fprintf_filtered(stream, "\n"); + + if (pretty) print_spaces_filtered (4 + 2 * recurse, stream); + fprintf_filtered(stream, "}"); + + if (TREE_RIGHT(node) != 0) + { + node = TREE_RIGHT(node); + while ((left = TREE_LEFT(node))) + { + node = left; + } + } + else + { + tmp_node = TREE_PARENT(node); + while (node == TREE_RIGHT(node)) + { + node = tmp_node; + tmp_node = TREE_PARENT(node); + } + if (TREE_RIGHT(node) != tmp_node) + { + node = tmp_node; + } + } + + if (idx != count - 1) fprintf_filtered(stream, ", "); + if (pretty) + { + fprintf_filtered(stream, "\n"); + } + } + free(b_key); + free(b_value); + } + if (pretty) print_spaces_filtered (2 * recurse, stream); + fprintf_filtered (stream, "}"); + if (recurse == 0) fprintf_filtered (stream, "\n"); + } + + free(inner_key); + free(inner_value); +} + +void +cp_print_stl_string(struct type *type, CORE_ADDR address, + struct ui_file *stream, int format, int recurse, + enum val_prettyprint pretty) +{ + struct type *char_type; + struct frame_info *current_frame; + struct block *block; + int ptr_size; + int pc; + CORE_ADDR string_ptr; + + current_frame = get_current_frame (); + pc = get_frame_address_in_block (current_frame); + block = block_for_pc (pc); + char_type = cp_get_type("char *", block); + ptr_size = TYPE_LENGTH(char_type); + + string_ptr = read_memory_integer (address, ptr_size); + val_print_string (string_ptr, -1, 1, stream); +} + void cp_print_value_fields (struct type *type, struct type *real_type, const gdb_byte *valaddr, int offset, CORE_ADDR address, @@ -161,6 +683,35 @@ CHECK_TYPEDEF (type); + if (stlprint) + { + if (!strncmp(type->main_type->name, "std::vector<", 12)) + { + cp_print_stl_vector(type, address, stream, format, recurse, pretty); + return; + } + if (!strncmp(type->main_type->name, "std::list<", 10)) + { + cp_print_stl_list(type, address, stream, format, recurse, pretty); + return; + } + if (!strncmp(type->main_type->name, "std::set<", 9) || !strncmp(type->main_type->name, "std::multiset<", 14)) + { + cp_print_stl_set(type, address, stream, format, recurse, pretty); + return; + } + if (!strncmp(type->main_type->name, "std::map<", 9) || !strncmp(type->main_type->name, "std::multimap<", 14)) + { + cp_print_stl_map(type, address, stream, format, recurse, pretty); + return; + } + if (!strncmp(type->main_type->name, "std::basic_string