From 8514e31898f206915bbae2970285b1f35cd192ad Mon Sep 17 00:00:00 2001 From: Gabriel Dos Reis Date: Sun, 9 Jul 2000 07:51:26 +0000 Subject: [PATCH] diagnostic.c (diagnostic_args): New macro. 2000-07-09 Gabriel Dos Reis * diagnostic.c (diagnostic_args): New macro. (diagnostic_msg): Likewise. (output_formatted_integer): Likewise. (output_state): New data type. (digit_buffer): Make global. (output_add_integer): Rename to output_decimal. Squeeze digit_buffer. (output_long_decimal, output_unsigned_decimal, output_long_unsigned_decimal, output_octal, output_long_octal, output_hexadecimal, output_long_hexadecimal): New functions. (output_append_r): New function. (output_append): Tweak. (output_flush_on): Rename to output_to_stream. (output_format): Change prototype. Improve documentation. Handle more format specifiers. (build_location_prefix): Rename to context_as_prefix. (output_notice): Rename to output_do_printf. (output_printf): Tweak. (line_wrapper_printf): Likewise. (vline_wrapper_message_with_location): Adjust call to renamed functions. (v_message_with_decl): Likewise. (default_print_error_function): Likewise. (save_output_state): New function. (restore_output_state): Likewise. (output_do_verbatim): Likewise. (output_verbatim): Define. (verbatim): Likewise. * diagnostic.h (printer_fn): Change return type from void to int. Improve documentation. (output_add_integer): Rename to output_decimal. (output_flush_on, output_format): Don't export. (output_verbatim, verbatim): Declare. From-SVN: r34932 --- gcc/ChangeLog | 37 +++++ gcc/diagnostic.c | 382 ++++++++++++++++++++++++++++++++++++++++------- gcc/diagnostic.h | 12 +- 3 files changed, 369 insertions(+), 62 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4d33224b012..75a21427217 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,40 @@ +2000-07-09 Gabriel Dos Reis + + * diagnostic.c (diagnostic_args): New macro. + (diagnostic_msg): Likewise. + (output_formatted_integer): Likewise. + (output_state): New data type. + (digit_buffer): Make global. + (output_add_integer): Rename to output_decimal. Squeeze + digit_buffer. + (output_long_decimal, output_unsigned_decimal, + output_long_unsigned_decimal, output_octal, output_long_octal, + output_hexadecimal, output_long_hexadecimal): New functions. + (output_append_r): New function. + (output_append): Tweak. + (output_flush_on): Rename to output_to_stream. + (output_format): Change prototype. Improve documentation. Handle + more format specifiers. + (build_location_prefix): Rename to context_as_prefix. + (output_notice): Rename to output_do_printf. + (output_printf): Tweak. + (line_wrapper_printf): Likewise. + (vline_wrapper_message_with_location): Adjust call to renamed + functions. + (v_message_with_decl): Likewise. + (default_print_error_function): Likewise. + (save_output_state): New function. + (restore_output_state): Likewise. + (output_do_verbatim): Likewise. + (output_verbatim): Define. + (verbatim): Likewise. + + * diagnostic.h (printer_fn): Change return type from void to int. + Improve documentation. + (output_add_integer): Rename to output_decimal. + (output_flush_on, output_format): Don't export. + (output_verbatim, verbatim): Declare. + 2000-07-08 Toon Moene * fold-const.c (extract_muldiv) case PLUS_EXPR, MINUS_EXPR: diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 634ff5106cc..3d7f0e93919 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -42,14 +42,40 @@ Boston, MA 02111-1307, USA. */ #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free +#define diagnostic_args diagnostic_buffer->format_args +#define diagnostic_msg diagnostic_buffer->cursor + +#define output_formatted_integer(BUFFER, FORMAT, INTEGER) \ + do { \ + sprintf (digit_buffer, FORMAT, INTEGER); \ + output_add_string (BUFFER, digit_buffer); \ + } while (0) + +/* This data structure serves to save/restore an output_buffer state. */ +typedef struct +{ + const char *prefix; + int maximum_length; + int ideal_maximum_length; + int emitted_prefix_p; + int prefixing_rule; + const char *cursor; + va_list format_args; +} output_state; + + /* Prototypes. */ static int doing_line_wrapping PARAMS ((void)); +static void output_do_verbatim PARAMS ((output_buffer *)); +static void output_to_stream PARAMS ((output_buffer *, FILE *)); +static void output_format PARAMS ((output_buffer *)); + static char *vbuild_message_string PARAMS ((const char *, va_list)); static char *build_message_string PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1; -static char *build_location_prefix PARAMS ((const char *, int, int)); -static void output_notice PARAMS ((output_buffer *, const char *)); +static char *context_as_prefix PARAMS ((const char *, int, int)); +static void output_do_printf PARAMS ((output_buffer *, const char *)); static void line_wrapper_printf PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2; static void vline_wrapper_message_with_location PARAMS ((const char *, int, @@ -77,6 +103,20 @@ static void report_file_and_line PARAMS ((const char *, int, int)); static void vnotice PARAMS ((FILE *, const char *, va_list)); static void set_real_maximum_length PARAMS ((output_buffer *)); +static void save_output_state PARAMS ((const output_buffer *, output_state *)); +static void restore_output_state PARAMS ((const output_state *, + output_buffer *)); + +static void output_unsigned_decimal PARAMS ((output_buffer *, unsigned int)); +static void output_long_decimal PARAMS ((output_buffer *, long int)); +static void output_long_unsigned_decimal PARAMS ((output_buffer *, + long unsigned int)); +static void output_octal PARAMS ((output_buffer *, int)); +static void output_long_octal PARAMS ((output_buffer *, long int)); +static void output_hexadecimal PARAMS ((output_buffer *, int)); +static void output_long_hexadecimal PARAMS ((output_buffer *, long int)); +static void output_append_r PARAMS ((output_buffer *, const char *, int)); + extern int rtl_dump_and_exit; extern int inhibit_warnings; extern int warnings_are_errors; @@ -86,6 +126,10 @@ extern int errorcount; /* Front-end specific tree formatter, if non-NULL. */ printer_fn lang_printer = NULL; +/* This must be large enough to hold any printed integer or + floating-point value. */ +static char digit_buffer[128]; + /* An output_buffer surrogate for stderr. */ static output_buffer global_output_buffer; output_buffer *diagnostic_buffer = &global_output_buffer; @@ -345,41 +389,103 @@ output_add_space (buffer) ++buffer->line_length; } -/* Add the stringified version of an integer to BUFFER. */ +/* These functions format an INTEGER into BUFFER as suggested by their + names. */ void -output_add_integer (buffer, i) +output_decimal (buffer, i) output_buffer *buffer; - HOST_WIDE_INT i; + int i; { - /* This must be large enough to hold any printed integer or - floating-point value. */ - static char digit_buffer[128]; + output_formatted_integer (buffer, "%d", i); +} - sprintf (digit_buffer, HOST_WIDE_INT_PRINT_DEC, i); - output_add_string (buffer, digit_buffer); +static void +output_long_decimal (buffer, i) + output_buffer *buffer; + long int i; +{ + output_formatted_integer (buffer, "%ld", i); } -/* Append a string deliminated by START and END to BUFFER. No wrapping is - done. The caller must ensure that it is safe to do so. */ +static void +output_unsigned_decimal (buffer, i) + output_buffer *buffer; + unsigned int i; +{ + output_formatted_integer (buffer, "%u", i); +} + +static void +output_long_unsigned_decimal (buffer, i) + output_buffer *buffer; + long unsigned int i; +{ + output_formatted_integer (buffer, "%lu", i); +} + +static void +output_octal (buffer, i) + output_buffer *buffer; + int i; +{ + output_formatted_integer (buffer, "%o", i); +} + +static void +output_long_octal (buffer, i) + output_buffer *buffer; + long int i; +{ + output_formatted_integer (buffer, "%lo", i); +} + +static void +output_hexadecimal (buffer, i) + output_buffer *buffer; + int i; +{ + output_formatted_integer (buffer, "%x", i); +} +static void +output_long_hexadecimal (buffer, i) + output_buffer *buffer; + long int i; +{ + output_formatted_integer (buffer, "%lx", i); +} + +/* Append to BUFFER a string specified by its STARTING character + and LENGTH. */ +static void +output_append_r (buffer, start, length) + output_buffer *buffer; + const char *start; + int length; +{ + obstack_grow (&buffer->obstack, start, length); + buffer->line_length += length; +} + +/* Append a string deliminated by START and END to BUFFER. No wrapping is + done. However, if beginning a new line then emit BUFFER->PREFIX and + skip any leading whitespace if appropriate. The caller must ensure + that it is safe to do so. */ void output_append (buffer, start, end) output_buffer *buffer; const char *start; const char *end; { - int n; - /* Emit prefix and skip whitespace if we're starting a new line. */ if (buffer->line_length == 0) { output_emit_prefix (buffer); - while (start != end && *start == ' ') - ++start; + if (output_is_line_wrapping (buffer)) + while (start != end && *start == ' ') + ++start; } - n = end - start; - obstack_grow (&buffer->obstack, start, n); - buffer->line_length += n; + output_append_r (buffer, start, end - start); } /* Wrap a STRing into BUFFER. */ @@ -418,8 +524,8 @@ output_add_string (buffer, str) /* Flush the content of BUFFER onto FILE and reinitialize BUFFER. */ -void -output_flush_on (buffer, file) +static void +output_to_stream (buffer, file) output_buffer *buffer; FILE *file; { @@ -428,14 +534,26 @@ output_flush_on (buffer, file) output_clear (buffer); } -/* Format MESSAGE into BUFFER. */ -void -output_format (buffer, msg) +/* Format a message pointed to by BUFFER->CURSOR using BUFFER->CURSOR + as appropriate. The following format specifiers are recognized as + being language independent: + %d, %i: (signed) integer in base ten. + %u: unsigned integer in base ten. + %o: (signed) integer in base eight. + %x: (signged) integer in base sixteen. + %ld, %li, %lo, %lu, %lx: long versions of the above. + %c: character. + %s: string. + %%: `%'. + %*.s: a substring the length of which is specified by an integer. */ +static void +output_format (buffer) output_buffer *buffer; - const char *msg; { - for (buffer->cursor = msg; *buffer->cursor; ++buffer->cursor) + const char *msg = buffer->cursor; + for (; *buffer->cursor; ++buffer->cursor) { + int long_integer = 0; /* Ignore text. */ if (*buffer->cursor != '%') { @@ -443,24 +561,86 @@ output_format (buffer, msg) continue; } - /* We got a '%'. Let's see what happens. */ - ++buffer->cursor; - - /* Let's handle the traditional cases. */ - if (*buffer->cursor == 's') - output_add_string (buffer, va_arg (buffer->format_args, const char *)); - else if (*buffer->cursor == 'd') - output_add_integer (buffer, va_arg (buffer->format_args, int)); - else if (*buffer->cursor == '%') - /* It was a '%%'. Just output a '%'. */ - output_add_character (buffer, '%'); - else if (lang_printer) - (*lang_printer) (buffer); - else + /* We got a '%'. Let's see what happens. Record whether we're + parsing a long integer format specifier. */ + if (*++buffer->cursor == 'l') { - /* Hmmm. The front-end failed to install a format translator - but called us with an unrecognized format. Sorry. */ - abort(); + long_integer = 1; + ++buffer->cursor; + } + + /* Handle %c, %d, %i, %ld, %li, %lo, %lu, %lx, %o, %s, %u, + %x, %.*s; %%. And nothing else. Front-ends should install + printers to grok language specific format specifiers. */ + switch (*buffer->cursor) + { + case 'c': + output_add_character + (buffer, va_arg (buffer->format_args, int)); + break; + + case 'd': + case 'i': + if (long_integer) + output_long_decimal + (buffer, va_arg (buffer->format_args, long int)); + else + output_decimal (buffer, va_arg (buffer->format_args, int)); + break; + + case 'o': + if (long_integer) + output_long_octal + (buffer, va_arg (buffer->format_args, long int)); + else + output_octal (buffer, va_arg (buffer->format_args, int)); + break; + + case 's': + output_add_string + (buffer, va_arg (buffer->format_args, const char *)); + break; + + case 'u': + if (long_integer) + output_long_unsigned_decimal + (buffer, va_arg (buffer->format_args, long unsigned int)); + else + output_unsigned_decimal + (buffer, va_arg (buffer->format_args, unsigned int)); + + case 'x': + if (long_integer) + output_long_hexadecimal + (buffer, va_arg (buffer->format_args, long int)); + else + output_hexadecimal (buffer, va_arg (buffer->format_args, int)); + break; + + case '%': + output_add_character (buffer, '%'); + break; + + case '.': + { + int n; + /* We handle no precision specifier but `%.*s'. */ + if (*++buffer->cursor != '*') + abort (); + else if (*++buffer->cursor != 's') + abort(); + n = va_arg (buffer->format_args, int); + output_append (buffer, msg, msg + n); + } + break; + + default: + if (!lang_printer || !(*lang_printer) (buffer)) + { + /* Hmmm. The front-end failed to install a format translator + but called us with an unrecognized format. Sorry. */ + abort(); + } } } output_finish (buffer); @@ -507,7 +687,7 @@ build_message_string VPARAMS ((const char *msgid, ...)) responsible for freeing the memory. */ static char * -build_location_prefix (file, line, warn) +context_as_prefix (file, line, warn) const char *file; int line; int warn; @@ -531,7 +711,7 @@ build_location_prefix (file, line, warn) /* Format a MESSAGE into BUFFER. Automatically wrap lines. */ static void -output_notice (buffer, msgid) +output_do_printf (buffer, msgid) output_buffer *buffer; const char *msgid; { @@ -552,17 +732,20 @@ output_printf VPARAMS ((struct output_buffer *buffer, const char *msgid, ...)) const char *msgid; #endif va_list ap; + va_list old_args; VA_START (ap, msgid); - #ifndef ANSI_PROTOTYPES buffer = va_arg (ap, struct output_buffer *); msgid = va_arg (ap, const char *); #endif + va_copy (old_args, buffer->format_args); va_copy (buffer->format_args, ap); - output_notice (buffer, msgid); + output_do_printf (buffer, msgid); va_end (buffer->format_args); + + va_copy (buffer->format_args, old_args); } @@ -578,7 +761,7 @@ line_wrapper_printf VPARAMS ((FILE *file, const char *msgid, ...)) #endif output_buffer buffer; - init_output_buffer (&buffer, NULL, diagnostic_message_length_per_line); + default_initialize_buffer (&buffer); VA_START (buffer.format_args, msgid); #ifndef ANSI_PROTOTYPES @@ -586,8 +769,8 @@ line_wrapper_printf VPARAMS ((FILE *file, const char *msgid, ...)) msgid = va_arg (buffer.format_args, const char *); #endif - output_notice (&buffer, msgid); - output_flush_on (&buffer, file); + output_do_printf (&buffer, msgid); + output_to_stream (&buffer, file); va_end (buffer.format_args); } @@ -603,11 +786,11 @@ vline_wrapper_message_with_location (file, line, warn, msgid, ap) { output_buffer buffer; - init_output_buffer (&buffer, build_location_prefix (file, line, warn), + init_output_buffer (&buffer, context_as_prefix (file, line, warn), diagnostic_message_length_per_line); va_copy (buffer.format_args, ap); - output_notice (&buffer, msgid); - output_flush_on (&buffer, stderr); + output_do_printf (&buffer, msgid); + output_to_stream (&buffer, stderr); output_destroy_prefix (&buffer); fputc ('\n', stderr); @@ -692,7 +875,7 @@ v_message_with_decl (decl, warn, msgid, ap) if (doing_line_wrapping ()) { init_output_buffer - (&buffer, build_location_prefix + (&buffer, context_as_prefix (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl), warn), diagnostic_message_length_per_line); } @@ -747,7 +930,7 @@ v_message_with_decl (decl, warn, msgid, ap) if (doing_line_wrapping ()) { va_copy (buffer.format_args, ap); - output_notice (&buffer, p); + output_do_printf (&buffer, p); va_copy (ap, buffer.format_args); } else @@ -756,7 +939,7 @@ v_message_with_decl (decl, warn, msgid, ap) if (doing_line_wrapping()) { - output_flush_on (&buffer, stderr); + output_to_stream (&buffer, stderr); output_destroy_prefix (&buffer); } @@ -1255,7 +1438,7 @@ default_print_error_function (file) last_error_function = current_function_decl; if (doing_line_wrapping ()) - output_flush_on (&buffer, stderr); + output_to_stream (&buffer, stderr); free ((char*) prefix); } @@ -1508,3 +1691,88 @@ warning VPARAMS ((const char *msgid, ...)) va_end (ap); } +/* Save BUFFER's STATE. */ +static void +save_output_state (buffer, state) + const output_buffer *buffer; + output_state *state; +{ + state->prefix = buffer->prefix; + state->maximum_length = buffer->maximum_length; + state->ideal_maximum_length = buffer->ideal_maximum_length; + state->emitted_prefix_p = buffer->emitted_prefix_p; + state->prefixing_rule = buffer->prefixing_rule; + state->cursor = buffer->cursor; + va_copy (state->format_args, buffer->format_args); +} + +/* Restore BUFFER's previously saved STATE. */ +static void +restore_output_state (state, buffer) + const output_state *state; + output_buffer *buffer; +{ + buffer->prefix = state->prefix; + buffer->maximum_length = state->maximum_length; + buffer->ideal_maximum_length = state->ideal_maximum_length; + buffer->emitted_prefix_p = state->emitted_prefix_p; + buffer->prefixing_rule = state->prefixing_rule; + buffer->cursor = state->cursor; + va_copy (buffer->format_args, state->format_args); +} + +/* Helper subroutine of output_verbatim and verbatim. Do the approriate + settings needed by BUFFER for a verbatim formatting. */ +static void +output_do_verbatim (buffer) + output_buffer *buffer; +{ + buffer->prefix = NULL; + buffer->prefixing_rule = DIAGNOSTICS_SHOW_PREFIX_NEVER; + output_set_maximum_length (buffer, 0); + output_format (buffer); +} + +/* Output MESSAGE verbatim into BUFFER. */ +void +output_verbatim VPARAMS ((output_buffer *buffer, const char *msg, ...)) +{ +#ifndef ANSI_PROTOTYPES + output_buffer *buffer; + const char *msg; +#endif + output_state previous_state; + va_list ap; + + VA_START (ap, msg); +#ifndef ANSI_PROTOTYPES + buffer = va_arg (ap, output_buffer *); + msg = va_arg (ap, const char *); +#endif + save_output_state (buffer, &previous_state); + buffer->cursor = msg; + va_copy (buffer->format_args, ap); + output_do_verbatim(buffer); + va_end (buffer->format_args); + restore_output_state (&previous_state, buffer); +} + +/* Same as above but use diagnostic_buffer. */ +void +verbatim VPARAMS ((const char *msg, ...)) +{ +#ifndef ANSI_PROTOTYPES + const char *msg; +#endif + output_state previous_state; + save_output_state (diagnostic_buffer, &previous_state); + VA_START (diagnostic_args, msg); +#ifndef ANSI_PROTOTYPES + msg = va_arg (diagnostic_args, const char *); +#endif + diagnostic_msg = msg; + output_do_verbatim (diagnostic_buffer); + output_to_stream (diagnostic_buffer, stderr); + va_end (diagnostic_args); + restore_output_state (&previous_state, diagnostic_buffer); +} diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index e8a2d67af90..5699d180c19 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -32,8 +32,9 @@ typedef struct output_buffer output_buffer; #define DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE 0x2 /* The type of front-end specific hook that formats trees into an - output_buffer. */ -typedef void (*printer_fn) PARAMS ((output_buffer *)); + output_buffer. A language specific printer returns a truth value if + everything goes well. */ +typedef int (*printer_fn) PARAMS ((output_buffer *)); /* The output buffer datatype. This is best seen as an abstract datatype. */ struct output_buffer @@ -109,14 +110,15 @@ int output_space_left PARAMS ((const output_buffer *)); void output_append PARAMS ((output_buffer *, const char *, const char *)); void output_add_character PARAMS ((output_buffer *, int)); -void output_add_integer PARAMS ((output_buffer *, HOST_WIDE_INT)); +void output_decimal PARAMS ((output_buffer *, int)); void output_add_string PARAMS ((output_buffer *, const char *)); const char *output_finish PARAMS ((output_buffer *)); -void output_flush_on PARAMS ((output_buffer *, FILE *)); void output_printf PARAMS ((output_buffer *, const char *, ...)) ATTRIBUTE_PRINTF_2; -void output_format PARAMS ((output_buffer *, const char *)); int output_is_line_wrapping PARAMS ((output_buffer *)); void set_message_prefixing_rule PARAMS ((int)); +void output_verbatim PARAMS ((output_buffer *, const char *, ...)) + ATTRIBUTE_PRINTF_2; +void verbatim PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1; #endif /* __GCC_DIAGNOSTIC_H__ */ -- 2.30.2