X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fpretty-print.c;h=8aa99787c59ab5fe5fa77d34f5498f74ca6a0a10;hb=4e73628c98a3f9f48a65d7e276b55a2cef0d4329;hp=3848c1a9510fa208a6fe1ed022ac134945c4a415;hpb=cc6b52a659eadc6209d1ec42259de5d58c419ad3;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c index 3848c1a9510..8aa99787c59 100644 --- a/gcc/pretty-print.c +++ b/gcc/pretty-print.c @@ -1,12 +1,13 @@ /* Various declarations for language-independent pretty-print subroutines. - Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. GCC 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 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,21 +16,18 @@ 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 GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" -#undef FLOAT /* This is for hpux. They should change hpux. */ -#undef FFS /* Some systems define this in param.h. */ #include "system.h" #include "coretypes.h" #include "intl.h" #include "pretty-print.h" -#include "tree.h" -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free +#if HAVE_ICONV +#include +#endif /* A pointer to the formatted diagnostic message. */ #define pp_formatted_text_data(PP) \ @@ -51,7 +49,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA break; \ \ case 2: \ - pp_scalar (PP, "%ll" F, va_arg (ARG, long long T)); \ + pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T)); \ break; \ \ default: \ @@ -186,8 +184,6 @@ pp_base_indent (pretty_printer *pp) %.*s: a substring the length of which is specified by an argument integer. %Ns: likewise, but length specified as constant in the format string. - %H: location_t. - %J: a decl tree, from which DECL_SOURCE_LOCATION will be recorded. Flag 'q': quote formatted text (must come immediately after '%'). Arguments can be used sequentially, or through %N$ resp. *N$ @@ -230,7 +226,7 @@ pp_base_format (pretty_printer *pp, text_info *text) this point. */ memset (formatters, 0, sizeof formatters); - + for (p = text->format_spec; *p; ) { while (*p != '\0' && *p != '%') @@ -246,7 +242,7 @@ pp_base_format (pretty_printer *pp, text_info *text) { case '\0': gcc_unreachable (); - + case '%': obstack_1grow (&buffer->chunk_obstack, '%'); p++; @@ -363,7 +359,7 @@ pp_base_format (pretty_printer *pp, text_info *text) gcc_assert (chunk < PP_NL_ARGMAX * 2); args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *); args[chunk] = 0; - + /* Set output to the argument obstack, and switch line-wrapping and prefixing off. */ buffer->obstack = &buffer->chunk_obstack; @@ -471,22 +467,6 @@ pp_base_format (pretty_printer *pp, text_info *text) (pp, *text->args_ptr, precision, unsigned, "x"); break; - case 'H': - { - location_t *locus = va_arg (*text->args_ptr, location_t *); - gcc_assert (text->locus != NULL); - *text->locus = *locus; - } - break; - - case 'J': - { - tree t = va_arg (*text->args_ptr, tree); - gcc_assert (text->locus != NULL); - *text->locus = DECL_SOURCE_LOCATION (t); - } - break; - case '.': { int n; @@ -634,7 +614,7 @@ pp_base_destroy_prefix (pretty_printer *pp) { if (pp->prefix != NULL) { - free ((char *) pp->prefix); + free (CONST_CAST (char *, pp->prefix)); pp->prefix = NULL; } } @@ -677,7 +657,7 @@ void pp_construct (pretty_printer *pp, const char *prefix, int maximum_length) { memset (pp, 0, sizeof (pretty_printer)); - pp->buffer = xcalloc (1, sizeof (output_buffer)); + pp->buffer = XCNEW (output_buffer); obstack_init (&pp->buffer->chunk_obstack); obstack_init (&pp->buffer->formatted_obstack); pp->buffer->obstack = &pp->buffer->formatted_obstack; @@ -685,6 +665,7 @@ pp_construct (pretty_printer *pp, const char *prefix, int maximum_length) pp_line_cutoff (pp) = maximum_length; pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_ONCE; pp_set_prefix (pp, prefix); + pp_translate_identifiers (pp) = true; } /* Append a string delimited by START and END to the output area of @@ -815,3 +796,226 @@ pp_base_maybe_space (pretty_printer *pp) pp_base (pp)->padding = pp_none; } } + +/* The string starting at P has LEN (at least 1) bytes left; if they + start with a valid UTF-8 sequence, return the length of that + sequence and set *VALUE to the value of that sequence, and + otherwise return 0 and set *VALUE to (unsigned int) -1. */ + +static int +decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value) +{ + unsigned int t = *p; + + if (len == 0) + abort (); + if (t & 0x80) + { + size_t utf8_len = 0; + unsigned int ch; + size_t i; + for (t = *p; t & 0x80; t <<= 1) + utf8_len++; + + if (utf8_len > len || utf8_len < 2 || utf8_len > 6) + { + *value = (unsigned int) -1; + return 0; + } + ch = *p & ((1 << (7 - utf8_len)) - 1); + for (i = 1; i < utf8_len; i++) + { + unsigned int u = p[i]; + if ((u & 0xC0) != 0x80) + { + *value = (unsigned int) -1; + return 0; + } + ch = (ch << 6) | (u & 0x3F); + } + if ( (ch <= 0x7F && utf8_len > 1) + || (ch <= 0x7FF && utf8_len > 2) + || (ch <= 0xFFFF && utf8_len > 3) + || (ch <= 0x1FFFFF && utf8_len > 4) + || (ch <= 0x3FFFFFF && utf8_len > 5) + || (ch >= 0xD800 && ch <= 0xDFFF)) + { + *value = (unsigned int) -1; + return 0; + } + *value = ch; + return utf8_len; + } + else + { + *value = t; + return 1; + } +} + +/* Allocator for identifier_to_locale and corresponding function to + free memory. */ + +void *(*identifier_to_locale_alloc) (size_t) = xmalloc; +void (*identifier_to_locale_free) (void *) = free; + +/* Given IDENT, an identifier in the internal encoding, return a + version of IDENT suitable for diagnostics in the locale character + set: either IDENT itself, or a string, allocated using + identifier_to_locale_alloc, converted to the locale character set + and using escape sequences if not representable in the locale + character set or containing control characters or invalid byte + sequences. Existing backslashes in IDENT are not doubled, so the + result may not uniquely specify the contents of an arbitrary byte + sequence identifier. */ + +const char * +identifier_to_locale (const char *ident) +{ + const unsigned char *uid = (const unsigned char *) ident; + size_t idlen = strlen (ident); + bool valid_printable_utf8 = true; + bool all_ascii = true; + size_t i; + + for (i = 0; i < idlen;) + { + unsigned int c; + size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c); + if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F)) + { + valid_printable_utf8 = false; + break; + } + if (utf8_len > 1) + all_ascii = false; + i += utf8_len; + } + + /* If IDENT contains invalid UTF-8 sequences (which may occur with + attributes putting arbitrary byte sequences in identifiers), or + control characters, we use octal escape sequences for all bytes + outside printable ASCII. */ + if (!valid_printable_utf8) + { + char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1); + char *p = ret; + for (i = 0; i < idlen; i++) + { + if (uid[i] > 0x1F && uid[i] < 0x7F) + *p++ = uid[i]; + else + { + sprintf (p, "\\%03o", uid[i]); + p += 4; + } + } + *p = 0; + return ret; + } + + /* Otherwise, if it is valid printable ASCII, or printable UTF-8 + with the locale character set being UTF-8, IDENT is used. */ + if (all_ascii || locale_utf8) + return ident; + + /* Otherwise IDENT is converted to the locale character set if + possible. */ +#if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV + if (locale_encoding != NULL) + { + iconv_t cd = iconv_open (locale_encoding, "UTF-8"); + bool conversion_ok = true; + char *ret = NULL; + if (cd != (iconv_t) -1) + { + size_t ret_alloc = 4 * idlen + 1; + for (;;) + { + /* Repeat the whole conversion process as needed with + larger buffers so non-reversible transformations can + always be detected. */ + ICONV_CONST char *inbuf = CONST_CAST (char *, ident); + char *outbuf; + size_t inbytesleft = idlen; + size_t outbytesleft = ret_alloc - 1; + size_t iconv_ret; + + ret = (char *) identifier_to_locale_alloc (ret_alloc); + outbuf = ret; + + if (iconv (cd, 0, 0, 0, 0) == (size_t) -1) + { + conversion_ok = false; + break; + } + + iconv_ret = iconv (cd, &inbuf, &inbytesleft, + &outbuf, &outbytesleft); + if (iconv_ret == (size_t) -1 || inbytesleft != 0) + { + if (errno == E2BIG) + { + ret_alloc *= 2; + identifier_to_locale_free (ret); + ret = NULL; + continue; + } + else + { + conversion_ok = false; + break; + } + } + else if (iconv_ret != 0) + { + conversion_ok = false; + break; + } + /* Return to initial shift state. */ + if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1) + { + if (errno == E2BIG) + { + ret_alloc *= 2; + identifier_to_locale_free (ret); + ret = NULL; + continue; + } + else + { + conversion_ok = false; + break; + } + } + *outbuf = 0; + break; + } + iconv_close (cd); + if (conversion_ok) + return ret; + } + } +#endif + + /* Otherwise, convert non-ASCII characters in IDENT to UCNs. */ + { + char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1); + char *p = ret; + for (i = 0; i < idlen;) + { + unsigned int c; + size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c); + if (utf8_len == 1) + *p++ = uid[i]; + else + { + sprintf (p, "\\U%08x", c); + p += 10; + } + i += utf8_len; + } + *p = 0; + return ret; + } +}