This patch fixes a Fortran diagnostic "regression".

With the current common diagnostic, the width shown with caret diagnostic is determined by:

    case OPT_fmessage_length_:
      pp_set_line_maximum_length (dc->printer, value);
      diagnostic_set_caret_max_width (dc, value);

plus

 diagnostic_set_caret_max_width (diagnostic_context *context, int value)
 {
   /* One minus to account for the leading empty space.  */
   value = value ? value - 1
     : (isatty (fileno (pp_buffer (context->printer)->stream))
       ? getenv_columns () - 1: INT_MAX);

   if (value <= 0)
     value = INT_MAX;

   context->caret_max_width = value;
 }

where getenv_columns looks at the environment variable COLUMNS.

Note that -fmessage-length= applies to the error message (wraps) _and_ the caret diagnostic (truncates) while the COLUMNS variable _only_ applies to the caret diagnostic. (BTW: The documentation currently does not mention COLUMNS.)

On most terminals, which I tried, COLUMNS does not seem to be set. In Fortran, error.c's get_terminal_width has a similar check, but additionally it uses ioctl to determine the terminal width.

I think with caret diagnostics, it is useful not to exceed the terminal width as having several "empty" lines before the "^" does not really improve the readability. Thus, I would propose to additionally use ioctl. Which rises two questions: (a) Should the COLUMNS environment variable or ioctl have a higher priority? [Fortran ranks ioctl higher; in the patch, for backward compatibilty, I rank COLUMNS higher.] (b) Should ioctl be always used or only for Fortran?

Comments?

Tobias
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 28ef81c..9a29300 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -82,18 +82,27 @@ file_name_as_prefix (diagnostic_context *context, const char *f)
 
 
 
 /* Return the value of the getenv("COLUMNS") as an integer. If the
-   value is not set to a positive integer, then return INT_MAX.  */
+   value is not set to a positive integer, use ioctl to get the
+   terminal width. If it fails, return INT_MAX.  */
 static int
-getenv_columns (void)
+getenv_columns_and_termwidth (void)
 {
   const char * s = getenv ("COLUMNS");
   if (s != NULL) {
     int n = atoi (s);
     if (n > 0)
       return n;
   }
+
+#ifdef TIOCGWINSZ
+  struct winsize w;
+  w.ws_col = 0;
+  if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
+    return w.ws_col;
+#endif
+
   return INT_MAX;
 }
 
 /* Set caret_max_width to value.  */
@@ -102,9 +111,9 @@ diagnostic_set_caret_max_width (diagnostic_context *context, int value)
 {
   /* One minus to account for the leading empty space.  */
   value = value ? value - 1 
     : (isatty (fileno (pp_buffer (context->printer)->stream))
-       ? getenv_columns () - 1: INT_MAX);
+       ? getenv_columns_and_termwidth () - 1: INT_MAX);
   
   if (value <= 0) 
     value = INT_MAX;
 

Reply via email to