Patchwork [libgfortran] PR47667 I/O for reals: READ waits for input after "i" and "n"

login
register
mail settings
Submitter Jerry DeLisle
Date Feb. 15, 2011, 5:51 a.m.
Message ID <4D5A1467.3030009@frontier.com>
Download mbox | patch
Permalink /patch/83189/
State New
Headers show

Comments

Jerry DeLisle - Feb. 15, 2011, 5:51 a.m.
On 02/12/2011 04:58 AM, Jerry DeLisle wrote:
> On 02/11/2011 11:27 PM, Janne Blomqvist wrote:
>> On Sat, Feb 12, 2011 at 01:48, Jerry DeLisle<jvdelisle@frontier.com> wrote:
>>> Hi,
>>>
>>> The attached patch was regression tested x86-64. This prevents calling
>>> eat_line and waiting for the next line.
>>>
>>> We don't really have a wat to do a test case.
>>>
>>> OK for trunk?
>>
>> Ok.
>>
>> As a curiosity, shouldn't eat_line() effectively be a no-op if the
>> current character is "\n"?
>>
>
> Yes, and a similar problem exists with logical and '.', integer and '+' and '-',
> and complex and '('.
>
> We could pass the current character into eat_line, but I would have to modify
> code everywhere it is used. Another option would be to put c inside the dtp
> structure, and then test it in eat_line. That is also quite intrusive.
>
> Since we have this same if block for all the different types I think i will just
> modify by using the same else if (c != '\n') in the specific places.
>
> I will resubmit the patch with those cases.
>

Here is an updated patch.  Regression tested on x86-64.  This patch adjusts 
reading for all types to avoid unwanted waiting for input. The patch also gives 
more flexible input for complex reads by permitting line feeds before and after 
'(', ',', and ')' This appears to be a common convention for reading complex values.

OK for trunk?

Regards,

Jerry

2011-02-14  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/47567
	* io/list_read.c (read_logical): Check for end of line before calling
	eat_line. (read_integer): Likewise. (parse_real): Don't unget the
	separator. Check for end of line before calling	eat_line.
	(read_complex): Allow line-end before and after parenthesis and comma.
	Check for end of line before calling eat_line. (read_real): Check for
	end of line before calling eat_line.
Tobias Burnus - Feb. 16, 2011, 7:21 p.m.
On 02/15/2011 06:51 AM, Jerry DeLisle wrote:
> Here is an updated patch.  Regression tested on x86-64.  This patch 
> adjusts reading for all types to avoid unwanted waiting for input. The 
> patch also gives more flexible input for complex reads by permitting 
> line feeds before and after '(', ',', and ')' This appears to be a 
> common convention for reading complex values.
>
> OK for trunk?

OK and thanks for the patch! I really wonder how long it will take until 
all such issues are fixed.

Tobias

> 2011-02-14  Jerry DeLisle <jvdelisle@gcc.gnu.org>
>
>     PR libgfortran/47567
>     * io/list_read.c (read_logical): Check for end of line before calling
>     eat_line. (read_integer): Likewise. (parse_real): Don't unget the
>     separator. Check for end of line before calling    eat_line.
>     (read_complex): Allow line-end before and after parenthesis and 
> comma.
>     Check for end of line before calling eat_line. (read_real): Check for
>     end of line before calling eat_line.

Patch

Index: list_read.c
===================================================================
--- list_read.c	(revision 170042)
+++ list_read.c	(working copy)
@@ -768,7 +768,7 @@  read_logical (st_parameter_dt *dtp, int length)
       hit_eof (dtp);
       return;
     }
-  else
+  else if (c != '\n')
     eat_line (dtp);
   sprintf (message, "Bad logical value while reading item %d",
 	      dtp->u.p.item_count);
@@ -906,7 +906,7 @@  read_integer (st_parameter_dt *dtp, int length)
       hit_eof (dtp);
       return;
     }
-  else
+  else if (c != '\n')
     eat_line (dtp);
   sprintf (message, "Bad integer for item %d in list input",
 	      dtp->u.p.item_count);
@@ -1104,6 +1104,7 @@  parse_real (st_parameter_dt *dtp, void *buffer, in
 
   if ((c = next_char (dtp)) == EOF)
     goto bad;
+    
   if (c == '-' || c == '+')
     {
       push_char (dtp, c);
@@ -1162,7 +1163,6 @@  parse_real (st_parameter_dt *dtp, void *buffer, in
 	  goto exp2;
 
 	CASE_SEPARATORS:
-	  unget_char (dtp, c);
 	  goto done;
 
 	default:
@@ -1273,7 +1273,7 @@  parse_real (st_parameter_dt *dtp, void *buffer, in
       hit_eof (dtp);
       return 1;
     }
-  else
+  else if (c != '\n')
     eat_line (dtp);
   sprintf (message, "Bad floating point number for item %d",
 	      dtp->u.p.item_count);
@@ -1310,15 +1310,22 @@  read_complex (st_parameter_dt *dtp, void * dest, i
       goto bad_complex;
     }
 
+eol_1:
   eat_spaces (dtp);
+  c = next_char (dtp);
+  if (c == '\n' || c== '\r')
+    goto eol_1;
+  else
+    unget_char (dtp, c);
+
   if (parse_real (dtp, dest, kind))
     return;
 
-eol_1:
+eol_2:
   eat_spaces (dtp);
   c = next_char (dtp);
   if (c == '\n' || c== '\r')
-    goto eol_1;
+    goto eol_2;
   else
     unget_char (dtp, c);
 
@@ -1326,18 +1333,25 @@  read_complex (st_parameter_dt *dtp, void * dest, i
       !=  (dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';'))
     goto bad_complex;
 
-eol_2:
+eol_3:
   eat_spaces (dtp);
   c = next_char (dtp);
   if (c == '\n' || c== '\r')
-    goto eol_2;
+    goto eol_3;
   else
     unget_char (dtp, c);
 
   if (parse_real (dtp, dest + size / 2, kind))
     return;
+    
+eol_4:
+  eat_spaces (dtp);
+  c = next_char (dtp);
+  if (c == '\n' || c== '\r')
+    goto eol_4;
+  else
+    unget_char (dtp, c);
 
-  eat_spaces (dtp);
   if (next_char (dtp) != ')')
     goto bad_complex;
 
@@ -1363,7 +1377,7 @@  read_complex (st_parameter_dt *dtp, void * dest, i
       hit_eof (dtp);
       return;
     }
-  else    
+  else if (c != '\n')   
     eat_line (dtp);
   sprintf (message, "Bad complex value in item %d of list input",
 	      dtp->u.p.item_count);
@@ -1726,8 +1740,9 @@  read_real (st_parameter_dt *dtp, void * dest, int
       hit_eof (dtp);
       return;
     }
-  else
+  else if (c != '\n')
     eat_line (dtp);
+
   sprintf (message, "Bad real number in item %d of list input",
 	      dtp->u.p.item_count);
   generate_error (&dtp->common, LIBERROR_READ_VALUE, message);