binutils-gdb/gdb/scm-valprint.c
Tom Tromey 6c7a06a3fa gdb:
2009-03-19  Tom Tromey  <tromey@redhat.com>
	    Julian Brown  <julian@codesourcery.com>

	PR i18n/7220, PR i18n/7821, PR exp/8815, PR exp/9103,
	PR i18n/9401, PR exp/9613:
	* NEWS: Update
	* value.h (value_typed_string): Declare.
	(val_print_string): Update.
	* valprint.h (print_char_chars): Update.
	* valprint.c (print_char_chars): Add type argument.  Update.
	(val_print_string): Likewise.
	* valops.c (value_typed_string): New function.
	* utils.c (host_char_to_target): New function.
	(parse_escape): Use host_char_to_target, host_hex_value.  Update.
	Remove '^' case.
	(no_control_char_error): Remove.
	* typeprint.c (print_type_scalar): Update.
	* scm-valprint.c (scm_scmval_print): Update.
	* scm-lang.h (scm_printchar, scm_printstr): Update.
	* scm-lang.c (scm_printchar): Add type argument.
	(scm_printstr): Likewise.
	* printcmd.c (print_formatted): Update.
	(print_scalar_formatted): Update.
	(printf_command) <wide_string_arg, wide_char_arg>: New constants.
	Handle '%lc' and '%ls'.
	* parser-defs.h (struct typed_stoken): New type.
	(struct stoken_vector): Likewise.
	(write_exp_string_vector): Declare.
	* parse.c (write_exp_string_vector): New function.
	* p-valprint.c (pascal_val_print): Update.
	* p-lang.h (is_pascal_string_type, pascal_printchar,
	pascal_printstr): Update.
	* p-lang.c (is_pascal_string_type): Remove 'char_size' argument.
	Add 'char_type' argument.
	(pascal_emit_char): Add type argument.
	(pascal_printchar): Likewise.
	(pascal_printstr): Likewise.
	* objc-lang.c (objc_emit_char): Add type argument.
	(objc_printchar): Likewise.
	(objc_printstr): Likewise.
	* macroexp.c (get_character_constant): Handle unicode characters.
	Use c_parse_escape.
	(get_string_literal): Handle unicode strings.  Use
	c_parse_escape.
	* m2-valprint.c (print_unpacked_pointer): Update.
	(m2_print_array_contents): Update.
	(m2_val_print): Update.
	* m2-lang.c (m2_emit_char): Add type argument.
	(m2_printchar): Likewise.
	(m2_printstr): Likewise.
	* language.h (struct language_defn) <la_printchar>: Add type
	argument.
	<la_printstr, la_emitchar>: Likewise.
	(LA_PRINT_CHAR): Likewise.
	(LA_PRINT_STRING): Likewise.
	(LA_EMIT_CHAR): Likewise.
	* language.c (unk_lang_emit_char): Add type argument.
	(unk_lang_printchar): Likewise.
	(unk_lang_printstr): Likewise.
	* jv-valprint.c (java_val_print): Update.
	* jv-lang.c (java_emit_char): Add type argument.
	* f-valprint.c (f_val_print): Update.
	* f-lang.c (f_emit_char): Add type argument.
	(f_printchar): Likewise.
	(f_printstr): Likewise.
	* expprint.c (print_subexp_standard): Update.
	* charset.h (target_wide_charset): Declare.
	(c_target_char_has_backslash_escape, c_parse_backslash,
	host_char_print_literally, host_char_to_target,
	target_char_to_host, target_char_to_control_char): Remove.
	(enum transliterations): New type.
	(convert_between_encodings): Declare.
	(HOST_ESCAPE_CHAR): New define.
	(host_letter_to_control_character, host_hex_value): Declare.
	(enum wchar_iterate_result): New enum.
	(struct wchar_iterator): Declare.
	(make_wchar_iterator, make_cleanup_wchar_iterator, wchar_iterator,
	wchar_push_back): Declare.
	* charset-list.h: New file.
	* c-valprint.c (textual_name): New function.
	(textual_element_type): Handle wide character types.
	(c_val_print): Pass original type to textual_element_type.  Handle
	wide character types.
	(c_value_print): Use textual_element_type.  Pass original type of
	value to val_print.
	* c-lang.h (enum c_string_type): New type.
	(c_printchar, c_printstr): Update.
	* c-lang.c (classify_type): New function.
	(print_wchar): Likewise.
	(c_emit_char): Add type argument.  Handle wide characters.
	(c_printchar): Likewise.
	(c_printstr): Add type argument.  Handle wide and multibyte
	character sets.
	(convert_ucn): New function.
	(emit_numeric_character): Likewise.
	(convert_octal): Likewise.
	(convert_hex): Likewise.
	(ADVANCE): New macro.
	(convert_escape): New function.
	(parse_one_string): Likewise.
	(evaluate_subexp_c): Likewise.
	(exp_descriptor_c): New global.
	(c_language_defn): Use exp_descriptor_c.
	(cplus_language_defn): Likewise.
	(asm_language_defn): Likewise.
	(minimal_language_defn): Likewise.
	(charset_for_string_type): New function.
	* c-exp.y (%union): Add 'svec' and 'tsval'.
	(CHAR): New token.
	(exp): Add CHAR production.
	(string_exp): Rewrite.
	(exp) <string_exp>: Rewrite.
	(tempbuf): Now global.
	(tempbuf_init): New global.
	(parse_string_or_char): New function.
	(yylex) <tempbuf>: Now global.
	<tokptr, tempbufindex, tempbufsize, token_string, class_prefix>:
	Remove.
	Handle 'u', 'U', and 'L' prefixes.  Call parse_string_or_char.
	(c_parse_escape): New function.
	* auxv.c (fprint_target_auxv): Update.
	* ada-valprint.c (ada_emit_char): Add type argument.
	(ada_printchar): Likewise.
	(ada_print_scalar): Update.
	(printstr): Add type argument.  Update calls to ada_emit_char.
	(ada_printstr): Add type argument.
	(ada_val_print_array): Update.
	(ada_val_print_1): Likewise.
	* ada-lang.c (emit_char): Add type argument.
	* ada-lang.h (ada_emit_char, ada_printchar, ada_printstr): Add
	type arguments.
	* gdb_locale.h: Include langinfo.h.
	* charset.c (_initialize_charset): Set default host charset from
	the locale.  Don't register charsets.  Add target-wide-charset
	commands.  Call find_charset_names.
	(struct charset, struct translation): Remove.
	(GDB_DEFAULT_HOST_CHARSET): Remove.
	(GDB_DEFAULT_TARGET_WIDE_CHARSET): New define.
	(target_wide_charset_name): New global.
	(show_host_charset_name): Handle "auto".
	(show_target_wide_charset_name): New function.
	(host_charset_enum, target_charset_enum): Remove.
	(charset_enum): New global.
	(all_charsets, register_charset, lookup_charset, all_translations,
	register_translation, lookup_translation): Remove.
	(simple_charset, ascii_print_literally, ascii_to_control): Remove.
	(iso_8859_print_literally, iso_8859_to_control,
	iso_8859_family_charset): Remove.
	(ebcdic_print_literally, ebcdic_to_control,
	ebcdic_family_charset): Remove.
	(struct cached_iconv, check_iconv_cache, cached_iconv_convert,
	register_iconv_charsets): Remove.
	(target_wide_charset_be_name, target_wide_charset_le_name): New
	globals.
	(identity_either_char_to_other): Remove.
	(set_be_le_names, validate): New functions.
	(backslashable, backslashed, represented): Remove.
	(default_c_target_char_has_backslash_escape): Remove.
	(default_c_parse_backslash, iconv_convert): Remove.
	(ascii_to_iso_8859_1_table, ascii_to_ebcdic_us_table,
	ascii_to_ibm1047_table, iso_8859_1_to_ascii_table,
	iso_8859_1_to_ebcdic_us_table, iso_8859_1_to_ibm1047_table,
	ebcdic_us_to_ascii_table, ebcdic_us_to_iso_8859_1_table,
	ebcdic_us_to_ibm1047_table, ibm1047_to_ascii_table,
	ibm1047_to_iso_8859_1_table, ibm1047_to_ebcdic_us_table): Remove.
	(table_convert_char, table_translation, simple_table_translation):
	Remove.
	(current_host_charset, current_target_charset,
	c_target_char_has_backslash_escape_func,
	c_target_char_has_backslash_escape_baton): Remove.
	(c_parse_backslash_func, c_parse_backslash_baton): Remove.
	(host_char_to_target_func, host_char_to_target_baton): Remove.
	(target_char_to_host_func, target_char_to_host_baton): Remove.
	(cached_iconv_host_to_target, cached_iconv_target_to_host):
	Remove.
	(lookup_charset_or_error, check_valid_host_charset): Remove.
	(set_host_and_target_charsets): Remove.
	(set_host_charset, set_target_charset): Remove.
	(set_host_charset_sfunc, set_target_charset_sfunc): Rewrite.
	(set_target_wide_charset_sfunc): New function.
	(show_charset): Print target wide character set.
	(host_charset, target_charset): Rewrite.
	(target_wide_charset): New function.
	(c_target_char_has_backslash_escape): Remove.
	(c_parse_backslash): Remove.
	(host_letter_to_control_character): New function.
	(host_char_print_literally): Remove.
	(host_hex_value): New function.
	(target_char_to_control_char): Remove.
	(cleanup_iconv): New function.
	(convert_between_encodings): New function.
	(target_char_to_host): Remove.
	(struct wchar_iterator): Define.
	(make_wchar_iterator, make_cleanup_wchar_iterator, wchar_iterator,
	wchar_push_back): New functions.
	(do_cleanup_iterator): New function.
	(char_ptr): New typedef.
	(charsets): New global.
	(add_one, find_charset_names): New functions.
	(default_charset_names): New global.
	(auto_host_charset_name): Likewise.
	* aclocal.m4, config.in, configure: Rebuild.
	* configure.ac: Call AM_LANGINFO_CODESET.
	(GDB_DEFAULT_HOST_CHARSET): Default to UTF-8.
	(AM_ICONV): Invoke earlier.
	* acinclude.m4: Include codeset.m4.  Subst LIBICONV_INCLUDE and
	LIBICONV_LIBDIR.  Check for libiconv in build tree.
	* Makefile.in (LIBICONV_LIBDIR, LIBICONV_INCLUDE): New macros.
	(INTERNAL_CFLAGS_BASE): Add LIBICONV_INCLUDE.
	(INTERNAL_LDFLAGS): Add LIBICONV_LIBDIR.
	* gdb_obstack.h (obstack_grow_wstr): New define.
        * gdb_wchar.h: New file.
        * defs.h: Include it.
gdb/testsuite:
	* gdb.base/store.exp: Update for change to escape output.
	* gdb.base/callfuncs.exp (fetch_all_registers): Update for change
	to escape output.
	* gdb.base/pointers.exp: Update for change to escape output.
	* gdb.base/long_long.exp (gdb_test_long_long): Update for change
	to escape output.
	* gdb.base/constvars.exp (do_constvar_tests): Update for change to
	escape output.
	* gdb.base/call-rt-st.exp (print_struct_call): Update for change
	to escape output.
	* gdb.cp/ref-types.exp (gdb_start_again): Update for change to
	escape output.
	* gdb.base/setvar.exp: Update for change to escape output.
	* lib/gdb.exp (default_gdb_start): Set LC_CTYPE to C.
	* gdb.base/printcmds.exp (test_print_all_chars): Update for change
	to escape output.
	(test_print_string_constants): Likewise.
	* gdb.base/charset.exp (valid_host_charset): Check size of
	wchar_t.  Handle UCS-2 and UCS-4.  Add tests for wide and unicode
	cases.  Handle "auto"-related output.
	* gdb.base/charset.c (char16_t, char32_t): New typedefs.
	(uvar, Uvar): New globals.
gdb/doc:
	* gdb.texinfo (Character Sets): Remove obsolete text.  Document
	set target-wide-charset.
	(Requirements): Mention iconv.
2009-03-20 23:04:40 +00:00

434 lines
10 KiB
C

/* Scheme/Guile language support routines for GDB, the GNU debugger.
Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "expression.h"
#include "parser-defs.h"
#include "language.h"
#include "value.h"
#include "scm-lang.h"
#include "valprint.h"
#include "gdbcore.h"
#include "c-lang.h"
#include "infcall.h"
#include "objfiles.h"
static void scm_ipruk (char *, LONGEST, struct ui_file *);
static void scm_scmlist_print (LONGEST, struct ui_file *, int,
const struct value_print_options *);
static int scm_inferior_print (LONGEST, struct ui_file *, int,
const struct value_print_options *);
/* Prints the SCM value VALUE by invoking the inferior, if appropraite.
Returns >= 0 on success; return -1 if the inferior cannot/should not
print VALUE. */
static int
scm_inferior_print (LONGEST value, struct ui_file *stream,
int recurse, const struct value_print_options *options)
{
struct objfile *objf;
struct gdbarch *gdbarch;
struct value *func, *arg, *result;
struct symbol *gdb_output_sym, *gdb_output_len_sym;
char *output;
int ret, output_len;
func = find_function_in_inferior ("gdb_print", &objf);
gdbarch = get_objfile_arch (objf);
arg = value_from_longest (builtin_type (gdbarch)->builtin_core_addr, value);
result = call_function_by_hand (func, 1, &arg);
ret = (int) value_as_long (result);
if (ret == 0)
{
/* XXX: Should we cache these symbols? */
gdb_output_sym =
lookup_symbol_global ("gdb_output", NULL, NULL, VAR_DOMAIN);
gdb_output_len_sym =
lookup_symbol_global ("gdb_output_length", NULL, NULL, VAR_DOMAIN);
if ((gdb_output_sym == NULL) || (gdb_output_len_sym == NULL))
ret = -1;
else
{
struct value *remote_buffer;
read_memory (SYMBOL_VALUE_ADDRESS (gdb_output_len_sym),
(char *) &output_len, sizeof (output_len));
output = (char *) alloca (output_len);
remote_buffer = value_at (builtin_type (gdbarch)->builtin_core_addr,
SYMBOL_VALUE_ADDRESS (gdb_output_sym));
read_memory (value_as_address (remote_buffer),
output, output_len);
ui_file_write (stream, output, output_len);
}
}
return ret;
}
/* {Names of immediate symbols}
* This table must agree with the declarations in scm.h: {Immediate Symbols}.*/
static char *scm_isymnames[] =
{
/* This table must agree with the declarations */
"and",
"begin",
"case",
"cond",
"do",
"if",
"lambda",
"let",
"let*",
"letrec",
"or",
"quote",
"set!",
"define",
#if 0
"literal-variable-ref",
"literal-variable-set!",
#endif
"apply",
"call-with-current-continuation",
/* user visible ISYMS */
/* other keywords */
/* Flags */
"#f",
"#t",
"#<undefined>",
"#<eof>",
"()",
"#<unspecified>"
};
static void
scm_scmlist_print (LONGEST svalue, struct ui_file *stream, int recurse,
const struct value_print_options *options)
{
unsigned int more = options->print_max;
if (recurse > 6)
{
fputs_filtered ("...", stream);
return;
}
scm_scmval_print (SCM_CAR (svalue), stream, recurse + 1, options);
svalue = SCM_CDR (svalue);
for (; SCM_NIMP (svalue); svalue = SCM_CDR (svalue))
{
if (SCM_NECONSP (svalue))
break;
fputs_filtered (" ", stream);
if (--more == 0)
{
fputs_filtered ("...", stream);
return;
}
scm_scmval_print (SCM_CAR (svalue), stream, recurse + 1, options);
}
if (SCM_NNULLP (svalue))
{
fputs_filtered (" . ", stream);
scm_scmval_print (svalue, stream, recurse + 1, options);
}
}
static void
scm_ipruk (char *hdr, LONGEST ptr, struct ui_file *stream)
{
fprintf_filtered (stream, "#<unknown-%s", hdr);
#define SCM_SIZE TYPE_LENGTH (builtin_type_scm)
if (SCM_CELLP (ptr))
fprintf_filtered (stream, " (0x%lx . 0x%lx) @",
(long) SCM_CAR (ptr), (long) SCM_CDR (ptr));
fprintf_filtered (stream, " 0x%s>", paddr_nz (ptr));
}
void
scm_scmval_print (LONGEST svalue, struct ui_file *stream,
int recurse, const struct value_print_options *options)
{
taloop:
switch (7 & (int) svalue)
{
case 2:
case 6:
print_longest (stream,
options->format ? options->format : 'd',
1, svalue >> 2);
break;
case 4:
if (SCM_ICHRP (svalue))
{
svalue = SCM_ICHR (svalue);
scm_printchar (svalue, builtin_type (current_gdbarch)->builtin_char,
stream);
break;
}
else if (SCM_IFLAGP (svalue)
&& (SCM_ISYMNUM (svalue)
< (sizeof scm_isymnames / sizeof (char *))))
{
fputs_filtered (SCM_ISYMCHARS (svalue), stream);
break;
}
else if (SCM_ILOCP (svalue))
{
fprintf_filtered (stream, "#@%ld%c%ld",
(long) SCM_IFRAME (svalue),
SCM_ICDRP (svalue) ? '-' : '+',
(long) SCM_IDIST (svalue));
break;
}
else
goto idef;
break;
case 1:
/* gloc */
svalue = SCM_CAR (svalue - 1);
goto taloop;
default:
idef:
scm_ipruk ("immediate", svalue, stream);
break;
case 0:
switch (SCM_TYP7 (svalue))
{
case scm_tcs_cons_gloc:
if (SCM_CDR (SCM_CAR (svalue) - 1L) == 0)
{
#if 0
SCM name;
#endif
fputs_filtered ("#<latte ", stream);
#if 1
fputs_filtered ("???", stream);
#else
name = ((SCM n *) (STRUCT_TYPE (exp)))[struct_i_name];
scm_lfwrite (CHARS (name),
(sizet) sizeof (char),
(sizet) LENGTH (name),
port);
#endif
fprintf_filtered (stream, " #X%s>", paddr_nz (svalue));
break;
}
case scm_tcs_cons_imcar:
case scm_tcs_cons_nimcar:
fputs_filtered ("(", stream);
scm_scmlist_print (svalue, stream, recurse + 1, options);
fputs_filtered (")", stream);
break;
case scm_tcs_closures:
fputs_filtered ("#<CLOSURE ", stream);
scm_scmlist_print (SCM_CODE (svalue), stream, recurse + 1, options);
fputs_filtered (">", stream);
break;
case scm_tc7_string:
{
int len = SCM_LENGTH (svalue);
CORE_ADDR addr = (CORE_ADDR) SCM_CDR (svalue);
int i;
int done = 0;
int buf_size;
gdb_byte buffer[64];
int truncate = options->print_max && len > (int) options->print_max;
if (truncate)
len = options->print_max;
fputs_filtered ("\"", stream);
for (; done < len; done += buf_size)
{
buf_size = min (len - done, 64);
read_memory (addr + done, buffer, buf_size);
for (i = 0; i < buf_size; ++i)
switch (buffer[i])
{
case '\"':
case '\\':
fputs_filtered ("\\", stream);
default:
fprintf_filtered (stream, "%c", buffer[i]);
}
}
fputs_filtered (truncate ? "...\"" : "\"", stream);
break;
}
break;
case scm_tcs_symbols:
{
int len = SCM_LENGTH (svalue);
char *str = alloca (len);
read_memory (SCM_CDR (svalue), (gdb_byte *) str, len + 1);
/* Should handle weird characters FIXME */
str[len] = '\0';
fputs_filtered (str, stream);
break;
}
case scm_tc7_vector:
{
int len = SCM_LENGTH (svalue);
int i;
LONGEST elements = SCM_CDR (svalue);
fputs_filtered ("#(", stream);
for (i = 0; i < len; ++i)
{
if (i > 0)
fputs_filtered (" ", stream);
scm_scmval_print (scm_get_field (elements, i), stream,
recurse + 1, options);
}
fputs_filtered (")", stream);
}
break;
#if 0
case tc7_lvector:
{
SCM result;
SCM hook;
hook = scm_get_lvector_hook (exp, LV_PRINT_FN);
if (hook == BOOL_F)
{
scm_puts ("#<locked-vector ", port);
scm_intprint (CDR (exp), 16, port);
scm_puts (">", port);
}
else
{
result
= scm_apply (hook,
scm_listify (exp, port,
(writing ? BOOL_T : BOOL_F),
SCM_UNDEFINED),
EOL);
if (result == BOOL_F)
goto punk;
}
break;
}
break;
case tc7_bvect:
case tc7_ivect:
case tc7_uvect:
case tc7_fvect:
case tc7_dvect:
case tc7_cvect:
scm_raprin1 (exp, port, writing);
break;
#endif
case scm_tcs_subrs:
{
int index = SCM_CAR (svalue) >> 8;
#if 1
char str[20];
sprintf (str, "#%d", index);
#else
char *str = index ? SCM_CHARS (scm_heap_org + index) : "";
#define SCM_CHARS(x) ((char *)(SCM_CDR(x)))
char *str = CHARS (SNAME (exp));
#endif
fprintf_filtered (stream, "#<primitive-procedure %s>",
str);
}
break;
#if 0
#ifdef CCLO
case tc7_cclo:
scm_puts ("#<compiled-closure ", port);
scm_iprin1 (CCLO_SUBR (exp), port, writing);
scm_putc ('>', port);
break;
#endif
case tc7_contin:
fprintf_filtered (stream, "#<continuation %d @ #X%lx >",
LENGTH (svalue),
(long) CHARS (svalue));
break;
case tc7_port:
i = PTOBNUM (exp);
if (i < scm_numptob
&& scm_ptobs[i].print
&& (scm_ptobs[i].print) (exp, port, writing))
break;
goto punk;
case tc7_smob:
i = SMOBNUM (exp);
if (i < scm_numsmob && scm_smobs[i].print
&& (scm_smobs[i].print) (exp, port, writing))
break;
goto punk;
#endif
default:
#if 0
punk:
#endif
scm_ipruk ("type", svalue, stream);
}
break;
}
}
int
scm_val_print (struct type *type, const gdb_byte *valaddr,
int embedded_offset, CORE_ADDR address,
struct ui_file *stream, int recurse,
const struct value_print_options *options)
{
if (is_scmvalue_type (type))
{
LONGEST svalue = extract_signed_integer (valaddr, TYPE_LENGTH (type));
if (scm_inferior_print (svalue, stream, recurse, options) >= 0)
{
}
else
{
scm_scmval_print (svalue, stream, recurse, options);
}
gdb_flush (stream);
return (0);
}
else
{
return c_val_print (type, valaddr, 0, address, stream, recurse, options);
}
}
int
scm_value_print (struct value *val, struct ui_file *stream,
const struct value_print_options *options)
{
struct value_print_options opts = *options;
opts.deref_ref = 1;
return (common_val_print (val, stream, 0, &opts, current_language));
}