diff options
author | Jerry DeLisle <jvdelisle@gcc.gnu> | 2014-03-15 20:31:33 +0000 |
---|---|---|
committer | Jerry DeLisle <jvdelisle@gcc.gnu> | 2014-03-15 20:31:33 +0000 |
commit | 80f3133e50f767462665bf137ba4d42dabd00448 (patch) | |
tree | 3def2fa7c2b988fcd525bd2cace58591d809dc1d /libgfortran | |
parent | 9ffeff04508c16929147eea96fa0b754abc457bc (diff) |
2014-03-15 Jerry DeLisle <jvdelisle@gcc.gnu>
Backport from mainline
PR libfortran/58324
PR libfortran/38199
* io/list_read.c (finish_list_read): Read one character to check
for the end of the file. If it is the end, then issue the file
end error message. If not, use eat_line to reach the end
without giving error. The next attempt to read will then
issue the error as described above.
* io/read.c (read_decimal): Quickly skip spaces to avoid calls
to next_char.
* io/unit.c (is_trim_ok): New helper function to check various
conditions to see if its OK to trim the internal unit string.
(get_internal_unit): Use LEN_TRIM to shorten selected internal
unit strings for optimizing READ. Enable this optimization for
formatted READ.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-4_8-branch@208595 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgfortran')
-rw-r--r-- | libgfortran/ChangeLog | 18 | ||||
-rw-r--r-- | libgfortran/io/list_read.c | 20 | ||||
-rw-r--r-- | libgfortran/io/read.c | 8 | ||||
-rw-r--r-- | libgfortran/io/unit.c | 70 |
4 files changed, 88 insertions, 28 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index fa07295f6ed..73336977d7a 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,21 @@ +2014-03-15 Jerry DeLisle <jvdelisle@gcc.gnu> + + Backport from mainline + PR libfortran/58324 + PR libfortran/38199 + * io/list_read.c (finish_list_read): Read one character to check + for the end of the file. If it is the end, then issue the file + end error message. If not, use eat_line to reach the end + without giving error. The next attempt to read will then + issue the error as described above. + * io/read.c (read_decimal): Quickly skip spaces to avoid calls + to next_char. + * io/unit.c (is_trim_ok): New helper function to check various + conditions to see if its OK to trim the internal unit string. + (get_internal_unit): Use LEN_TRIM to shorten selected internal + unit strings for optimizing READ. Enable this optimization for + formatted READ. + 2014-02-21 Jerry DeLisle <jvdelisle@gcc.gnu> Dominique d'Humieres <dominiq@lps.ens.fr> Steven G. Kargl <kargl@gcc.gnu.org> diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c index 7cafad0c55d..91ef8b5c864 100644 --- a/libgfortran/io/list_read.c +++ b/libgfortran/io/list_read.c @@ -2034,8 +2034,6 @@ list_formatted_read (st_parameter_dt *dtp, bt type, void *p, int kind, void finish_list_read (st_parameter_dt *dtp) { - int err; - free_saved (dtp); fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode); @@ -2046,12 +2044,22 @@ finish_list_read (st_parameter_dt *dtp) return; } - err = eat_line (dtp); - if (err == LIBERROR_END) + if (!is_internal_unit (dtp)) { - free_line (dtp); - hit_eof (dtp); + int c; + c = next_char (dtp); + if (c == EOF) + { + free_line (dtp); + hit_eof (dtp); + return; + } + if (c != '\n') + eat_line (dtp); } + + free_line (dtp); + } /* NAMELIST INPUT diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c index 2da1048f8ae..f45e1b4edfe 100644 --- a/libgfortran/io/read.c +++ b/libgfortran/io/read.c @@ -655,7 +655,13 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length) if (c == ' ') { - if (dtp->u.p.blank_status == BLANK_NULL) continue; + if (dtp->u.p.blank_status == BLANK_NULL) + { + /* Skip spaces. */ + for ( ; w > 0; p++, w--) + if (*p != ' ') break; + continue; + } if (dtp->u.p.blank_status == BLANK_ZERO) c = '0'; } diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c index f8c1516e0c7..ab61769a2eb 100644 --- a/libgfortran/io/unit.c +++ b/libgfortran/io/unit.c @@ -29,6 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "unix.h" #include <stdlib.h> #include <string.h> +#include <stdbool.h> /* IO locking rules: @@ -375,6 +376,38 @@ find_or_create_unit (int n) } +/* Helper function to check rank, stride, format string, and namelist. + This is used for optimization. You can't trim out blanks or shorten + the string if trailing spaces are significant. */ +static bool +is_trim_ok (st_parameter_dt *dtp) +{ + /* Check rank and stride. */ + if (dtp->internal_unit_desc + && (GFC_DESCRIPTOR_RANK (dtp->internal_unit_desc) > 1 + || GFC_DESCRIPTOR_STRIDE(dtp->internal_unit_desc, 0) != 1)) + return false; + /* Format strings can not have 'BZ' or '/'. */ + if (dtp->common.flags & IOPARM_DT_HAS_FORMAT) + { + char *p = dtp->format; + off_t i; + if (dtp->common.flags & IOPARM_DT_HAS_BLANK) + return false; + for (i = 0; i < dtp->format_len; i++) + { + if (p[i] == '/') return false; + if (p[i] == 'b' || p[i] == 'B') + if (p[i+1] == 'z' || p[i+1] == 'Z') + return false; + } + } + if (dtp->u.p.ionml) /* A namelist. */ + return false; + return true; +} + + gfc_unit * get_internal_unit (st_parameter_dt *dtp) { @@ -402,6 +435,22 @@ get_internal_unit (st_parameter_dt *dtp) some other file I/O unit. */ iunit->unit_number = -1; + /* As an optimization, adjust the unit record length to not + include trailing blanks. This will not work under certain conditions + where trailing blanks have significance. */ + if (dtp->u.p.mode == READING && is_trim_ok (dtp)) + { + int len; + if (dtp->common.unit == 0) + len = string_len_trim (dtp->internal_unit_len, + dtp->internal_unit); + else + len = string_len_trim_char4 (dtp->internal_unit_len, + (const gfc_char4_t*) dtp->internal_unit); + dtp->internal_unit_len = len; + iunit->recl = dtp->internal_unit_len; + } + /* Set up the looping specification from the array descriptor, if any. */ if (is_array_io (dtp)) @@ -414,27 +463,6 @@ get_internal_unit (st_parameter_dt *dtp) start_record *= iunit->recl; } - else - { - /* If we are not processing an array, adjust the unit record length not - to include trailing blanks for list-formatted reads. */ - if (dtp->u.p.mode == READING && !(dtp->common.flags & IOPARM_DT_HAS_FORMAT)) - { - if (dtp->common.unit == 0) - { - dtp->internal_unit_len = - string_len_trim (dtp->internal_unit_len, dtp->internal_unit); - iunit->recl = dtp->internal_unit_len; - } - else - { - dtp->internal_unit_len = - string_len_trim_char4 (dtp->internal_unit_len, - (const gfc_char4_t*) dtp->internal_unit); - iunit->recl = dtp->internal_unit_len; - } - } - } /* Set initial values for unit parameters. */ if (dtp->common.unit) |