diff options
author | Gabriel Dos Reis <gdr@codesourcery.com> | 2000-01-12 01:54:31 +0000 |
---|---|---|
committer | Gabriel Dos Reis <gdr@gcc.gnu.org> | 2000-01-12 01:54:31 +0000 |
commit | b903d81e07581446e35d3ce129ab4d91dc5463b6 (patch) | |
tree | 59ef54b6938fec73026db4d078e3259d6f372fb0 /gcc | |
parent | 40c79d58a3f379be9eb020e7d338319bf0e93907 (diff) | |
download | gcc-b903d81e07581446e35d3ce129ab4d91dc5463b6.zip gcc-b903d81e07581446e35d3ce129ab4d91dc5463b6.tar.gz gcc-b903d81e07581446e35d3ce129ab4d91dc5463b6.tar.bz2 |
2000-01-12 Gabriel Dos Reis <gdr@codesourcery.com>
Implement automatic line wrapping mode in the g++ front-end.
From-SVN: r31343
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/diagnostic.c | 439 | ||||
-rw-r--r-- | gcc/toplev.h | 1 |
4 files changed, 437 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 613166f..2dd2055 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2000-01-12 Gabriel Dos Reis <gdr@codesourcery.com> + + * toplev.h (set_message_length): Declare. + + * diagnostic.c (obstack_chunk_alloc): Define macro. + (obstack_chunk_free): Likewise. + (struct output_buffer): New data structure. + (vmessage): Remove. + (output_maximum_width): New variable. + (doing_line_wrapping, set_message_length, init_output_buffer, + get_output_prefix, output_space_left, emit_output_prefix, + output_newline, output_append, output_puts, dump_output, + vbuild_message_string, build_message_string, build_location_prefix, + voutput_notice, output_printf, line_wrapper_printf, + vline_wrapper_message_with_location): New functions. Implement + automatic line wrapping. + (v_message_with_decl): Make it handle automatic line wrapping. + (v_error_with_file_and_line): Likewise. + (v_warning_with_file_and_line): Likewise. + (announce_function): Likewise. + (default_print_error_function): Likewise. + 2000-01-11 16:24 -0800 Zack Weinberg <zack@wolery.cumb.org> * cpplib.h (struct cpp_options): Change lang_asm to char. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f07e10f..031947e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2000-01-12 Gabriel Dos Reis <gdr@codesourcery.com> + + * decl2.c (lang_decode_option): Handle automatic line wrapping + option. + 2000-01-11 Mark Mitchell <mark@codesourcery.com> * friend.c (do_friend): Don't resolve scopes when processing diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 1365e71..9d2eead 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -37,11 +37,41 @@ Boston, MA 02111-1307, USA. */ #include "insn-config.h" #include "toplev.h" #include "intl.h" +#include "obstack.h" +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +struct output_buffer +{ + struct obstack obstack; /* where we build the text to output */ + const char *prefix; /* prefix of every new line */ + int line_length; /* current line length (in characters) */ + int max_length; /* maximum characters per line */ +}; /* Prototypes. */ +static int doing_line_wrapping PROTO((void)); +static void init_output_buffer PROTO((struct output_buffer*, + const char *, int)); +static const char *get_output_prefix PROTO((const struct output_buffer *)); +static int output_space_left PROTO((const struct output_buffer *)); +static void emit_output_prefix PROTO((struct output_buffer *)); +static void output_newline PROTO((struct output_buffer *)); +static void output_append PROTO((struct output_buffer *, const char *, + const char *)); +static void output_puts PROTO((struct output_buffer *, const char *)); +static void dump_output PROTO((struct output_buffer *, FILE *)); +static const char *vbuild_message_string PROTO((const char *, va_list)); +static const char *build_message_string PVPROTO((const char *, ...)); +static const char *build_location_prefix PROTO((const char *, int, int)); +static void voutput_notice PROTO((struct output_buffer *, const char *, + va_list)); +static void output_printf PVPROTO((struct output_buffer *, const char *, ...)); +static void line_wrapper_printf PVPROTO((FILE *, const char *, ...)); +static void vline_wrapper_message_with_location PROTO((const char *, int, int, + const char *, va_list)); static void notice PVPROTO((const char *s, ...)) ATTRIBUTE_PRINTF_1; -static void vmessage PROTO((const char *, const char *, va_list)); static void v_message_with_file_and_line PROTO((const char *, int, int, const char *, va_list)); static void v_message_with_decl PROTO((tree, int, const char *, va_list)); @@ -88,7 +118,296 @@ static int last_error_tick; void (*print_error_function) PROTO((const char *)) = default_print_error_function; +/* Maximum characters per line in automatic line wrapping mode. + Non Zero means don't wrap lines. */ + +static int output_maximum_width = 0; +/* Predicate. Return 1 if we're in automatic line wrapping mode. */ + +static int +doing_line_wrapping () +{ + return output_maximum_width > 0; +} + +/* Set Maximum characters per line in automatic line wrapping mode. */ + +void +set_message_length (n) + int n; +{ + output_maximum_width = n; +} + +/* Construct an output BUFFER with PREFIX and of MAX_LENGTH characters + per line. */ + +static void +init_output_buffer (buffer, prefix, max_length) + struct output_buffer *buffer; + const char *prefix; + int max_length; +{ + obstack_init (&buffer->obstack); + buffer->prefix = prefix; + buffer->line_length = 0; + buffer->max_length = max_length; +} + +/* Return BUFFER's prefix. */ + +static const char * +get_output_prefix (buffer) + const struct output_buffer *buffer; +{ + return buffer->prefix; +} + +/* Return the amount of characters BUFFER can accept to + make a full line. */ + +static int +output_space_left (buffer) + const struct output_buffer *buffer; +{ + return buffer->max_length - buffer->line_length; +} + +/* Dump BUFFER's prefix. */ + +static void +emit_output_prefix (buffer) + struct output_buffer *buffer; +{ + if (buffer->prefix) + { + buffer->line_length = strlen (buffer->prefix); + obstack_grow (&buffer->obstack, buffer->prefix, buffer->line_length); + } +} + +/* Have BUFFER start a new line. */ + +static void +output_newline (buffer) + struct output_buffer *buffer; +{ + obstack_1grow (&buffer->obstack, '\n'); + buffer->line_length = 0; +} + +/* 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_append (buffer, start, end) + struct 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) + { + emit_output_prefix (buffer); + while (start != end && *start == ' ') + ++start; + } + n = end - start; + obstack_grow (&buffer->obstack, start, n); + buffer->line_length += n; +} + +/* Wrap a STRing into BUFFER. */ + +static void +output_puts (buffer, str) + struct output_buffer *buffer; + const char *str; +{ + const char *p = str; + + while (*str) + { + while (*p && *p != ' ' && *p != '\n') + ++p; + + if (p - str < output_space_left (buffer)) + output_append (buffer, str, p); + else + { + output_newline (buffer); + output_append (buffer, str, p); + } + + while (*p && *p == '\n') + { + output_newline (buffer); + ++p; + } + + str = p++; + } +} + +/* Dump the content of BUFFER into FILE. */ + +static void +dump_output (buffer, file) + struct output_buffer *buffer; + FILE *file; +{ + const char *text; + + obstack_1grow (&buffer->obstack, '\0'); + text = obstack_finish (&buffer->obstack); + fputs (text, file); + obstack_free (&buffer->obstack, (char *)text); + buffer->line_length = 0; +} + +static const char * +vbuild_message_string (msgid, ap) + const char *msgid; + va_list ap; +{ + char *str; + + vasprintf (&str, msgid, ap); + return str; +} + +/* Return a malloc'd string containing MSGID formatted a la + printf. The caller is reponsible for freeing the memory. */ + +static const char * +build_message_string VPROTO((const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + const char *msgid; +#endif + va_list ap; + const char *str; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + msgid = va_arg (ap, const char *); +#endif + + str = vbuild_message_string (msgid, ap); + + va_end (ap); + + return str; +} + + +/* Return a malloc'd string describing a location. The caller is + responsible for freeing the memory. */ + +static const char * +build_location_prefix (file, line, warn) + const char *file; + int line; + int warn; +{ + const char *fmt = file + ? (warn ? "%s:%d: warning: " : "%s:%d: ") + : (warn ? "%s: warning: " : "%s: "); + + return file + ? build_message_string (fmt, file, line) + : build_message_string (fmt, progname); +} + +/* Format a MESSAGE into BUFFER. Automatically wrap lines. */ + +static void +voutput_notice (buffer, msgid, ap) + struct output_buffer *buffer; + const char *msgid; + va_list ap; +{ + const char *message = vbuild_message_string (msgid, ap); + + output_puts (buffer, message); + free ((char *)message); +} + + +/* Format a message into BUFFER a la printf. */ + +static void +output_printf VPROTO((struct output_buffer *buffer, const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + struct output_buffer *buffer; + const char *msgid; +#endif + va_list ap; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + buffer = va_arg (ap, struct output_buffer *); + msgid = va_arg (ap, const char *); +#endif + + voutput_notice (buffer, msgid, ap); + va_end (ap); +} + + +/* Format a MESSAGE into FILE. Do line wrapping, starting new lines + with PREFIX. */ + +static void +line_wrapper_printf VPROTO((FILE *file, const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + FILE *file; + const char *msgid; +#endif + struct output_buffer buffer; + va_list ap; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + file = va_arg (ap, FILE *); + msgid = va_arg (ap, const char *); +#endif + + init_output_buffer (&buffer, (const char *)NULL, output_maximum_width); + voutput_notice (&buffer, msgid, ap); + dump_output (&buffer, file); + + va_end (ap); +} + + +static void +vline_wrapper_message_with_location (file, line, warn, msgid, ap) + const char *file; + int line; + int warn; + const char *msgid; + va_list ap; +{ + struct output_buffer buffer; + + init_output_buffer + (&buffer, build_location_prefix (file, line, warn), output_maximum_width); + voutput_notice (&buffer, msgid, ap); + dump_output (&buffer, stderr); + free ((char*)get_output_prefix (&buffer)); + fputc ('\n', stderr); +} + + /* Print the message MSGID in FILE. */ static void @@ -137,20 +456,6 @@ report_file_and_line (file, line, warn) notice ("warning: "); } -/* Print a PREFIXed MSGID. */ - -static void -vmessage (prefix, msgid, ap) - const char *prefix; - const char *msgid; - va_list ap; -{ - if (prefix) - fprintf (stderr, "%s: ", prefix); - - vfprintf (stderr, msgid, ap); -} - /* Print a message relevant to line LINE of file FILE. */ static void @@ -176,9 +481,17 @@ v_message_with_decl (decl, warn, msgid, ap) va_list ap; { const char *p; - - report_file_and_line (DECL_SOURCE_FILE (decl), - DECL_SOURCE_LINE (decl), warn); + struct output_buffer buffer; + + if (doing_line_wrapping ()) + init_output_buffer + (&buffer, + build_location_prefix (DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl), warn), + output_maximum_width); + else + report_file_and_line (DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl), warn); /* Do magic to get around lack of varargs support for insertion of arguments into existing list. We know that the decl is first; @@ -198,14 +511,22 @@ v_message_with_decl (decl, warn, msgid, ap) } if (p > _(msgid)) /* Print the left-hand substring. */ - fprintf (stderr, "%.*s", (int)(p - _(msgid)), _(msgid)); + { + if (doing_line_wrapping ()) + output_printf (&buffer, "%.*s", (int)(p - _(msgid)), _(msgid)); + else + fprintf (stderr, "%.*s", (int)(p - _(msgid)), _(msgid)); + } if (*p == '%') /* Print the name. */ { const char *n = (DECL_NAME (decl) ? (*decl_printable_name) (decl, 2) : "((anonymous))"); - fputs (n, stderr); + if (doing_line_wrapping ()) + output_puts (&buffer, n); + else + fputs (n, stderr); while (*p) { ++p; @@ -215,8 +536,19 @@ v_message_with_decl (decl, warn, msgid, ap) } if (*p) /* Print the rest of the message. */ - vmessage ((char *)NULL, p, ap); + { + if (doing_line_wrapping ()) + voutput_notice (&buffer, p, ap); + else + vfprintf (stderr, p, ap); + } + if (doing_line_wrapping()) + { + dump_output (&buffer, stderr); + free ((char *)get_output_prefix (&buffer)); + } + fputc ('\n', stderr); } @@ -268,7 +600,10 @@ v_error_with_file_and_line (file, line, msgid, ap) { count_error (0); report_error_function (file); - v_message_with_file_and_line (file, line, 0, msgid, ap); + if (doing_line_wrapping ()) + vline_wrapper_message_with_location (file, line, 0, msgid, ap); + else + v_message_with_file_and_line (file, line, 0, msgid, ap); } /* Report an error at the declaration DECL. @@ -347,7 +682,10 @@ v_warning_with_file_and_line (file, line, msgid, ap) if (count_error (1)) { report_error_function (file); - v_message_with_file_and_line (file, line, 1, msgid, ap); + if (doing_line_wrapping ()) + vline_wrapper_message_with_location (file, line, 1, msgid, ap); + else + v_message_with_file_and_line (file, line, 1, msgid, ap); } } @@ -635,7 +973,13 @@ announce_function (decl) if (rtl_dump_and_exit) fprintf (stderr, "%s ", IDENTIFIER_POINTER (DECL_NAME (decl))); else - fprintf (stderr, " %s", (*decl_printable_name) (decl, 2)); + { + if (doing_line_wrapping ()) + line_wrapper_printf + (stderr, " %s", (*decl_printable_name) (decl, 2)); + else + fprintf (stderr, " %s", (*decl_printable_name) (decl, 2)); + } fflush (stderr); need_error_newline = 1; last_error_function = current_function_decl; @@ -651,22 +995,57 @@ default_print_error_function (file) { if (last_error_function != current_function_decl) { + const char *prefix = NULL; + struct output_buffer buffer; + if (file) - fprintf (stderr, "%s: ", file); + prefix = build_message_string ("%s: ", file); + if (doing_line_wrapping ()) + init_output_buffer (&buffer, prefix, output_maximum_width); + else + { + if (file) + fprintf (stderr, "%s: ", file); + } + if (current_function_decl == NULL) - notice ("At top level:\n"); + { + if (doing_line_wrapping ()) + output_printf (&buffer, "At top level:\n"); + else + notice ("At top level:\n"); + } else { if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) - notice ("In method `%s':\n", - (*decl_printable_name) (current_function_decl, 2)); + { + if (doing_line_wrapping ()) + output_printf + (&buffer, "In method `%s':\n", + (*decl_printable_name) (current_function_decl, 2)); + else + notice ("In method `%s':\n", + (*decl_printable_name) (current_function_decl, 2)); + } else - notice ("In function `%s':\n", - (*decl_printable_name) (current_function_decl, 2)); + { + if (doing_line_wrapping ()) + output_printf + (&buffer, "In function `%s':\n", + (*decl_printable_name) (current_function_decl, 2)); + else + notice ("In function `%s':\n", + (*decl_printable_name) (current_function_decl, 2)); + } } last_error_function = current_function_decl; + + if (doing_line_wrapping ()) + dump_output (&buffer, stderr); + + free ((char *)prefix); } } diff --git a/gcc/toplev.h b/gcc/toplev.h index 6fb9f70..11c72ae 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -128,6 +128,7 @@ extern void fnotice PROTO ((FILE *, const char *, ...)) extern int wrapup_global_declarations PROTO ((union tree_node **, int)); extern void check_global_declarations PROTO ((union tree_node **, int)); extern void note_deferral_of_defined_inline_function PROTO ((union tree_node *)); +extern void set_message_length PROTO ((int)); extern int errorcount; extern int warningcount; extern int sorrycount; |