aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorThomas Koenig <Thomas.Koenig@online.de>2006-12-01 21:04:38 +0000
committerThomas Koenig <tkoenig@gcc.gnu.org>2006-12-01 21:04:38 +0000
commit07b3bbf2007bb9fab8b6c08321abf9c2cc7a2443 (patch)
treefa9d74bece4649b8f0f42522f03ff4b74899826b /gcc
parent7c6a62dd399b670aac5a1d8c96ba591b75df74b7 (diff)
downloadgcc-07b3bbf2007bb9fab8b6c08321abf9c2cc7a2443.zip
gcc-07b3bbf2007bb9fab8b6c08321abf9c2cc7a2443.tar.gz
gcc-07b3bbf2007bb9fab8b6c08321abf9c2cc7a2443.tar.bz2
re PR libfortran/29568 (implement unformatted files with subrecords (Intel style))
2006-12-01 Thomas Koenig <Thomas.Koenig@online.de> PR libfortran/29568 * gfortran.dg/convert_implied_open.f90: Change to new default record length. * gfortran.dg/unf_short_record_1.f90: Adapt to new error message. * gfortran.dg/unformatted_subrecords_1.f90: New test. 2006-12-01 Thomas Koenig <Thomas.Koenig@online.de> PR libfortran/29568 * gfortran.h (gfc_option_t): Add max_subrecord_length. (top level): Define MAX_SUBRECORD_LENGTH. * lang.opt: Add option -fmax-subrecord-length=. * trans-decl.c: Add new function set_max_subrecord_length. (gfc_generate_function_code): If we are within the main program and max_subrecord_length has been set, call set_max_subrecord_length. * options.c (gfc_init_options): Add defaults for max_subrecord_lenght, convert and record_marker. (gfc_handle_option): Add handling for -fmax_subrecord_length. * invoke.texi: Document the new default for -frecord-marker=<n>. 2006-12-01 Thomas Koenig <Thomas.Koenig@online.de> PR libfortran/29568 * libgfortran/libgfortran.h (compile_options_t): Add record_marker. (top level): Define GFC_MAX_SUBRECORD_LENGTH. * runtime/compile_options.c (set_record_marker): Change default to four-byte record marker. (set_max_subrecord_length): New function. * runtime/error.c (translate_error): Change error message for short record on unformatted read. * io/io.h (gfc_unit): Add recl_subrecord, bytes_left_subrecord and continued. * io/file_pos.c (unformatted_backspace): Change default of record marker size to four bytes. Loop over subrecords. * io/open.c: Default recl is max_offset. If compile_options.max_subrecord_length has been set, set set u->recl_subrecord to its value, to the maximum value otherwise. * io/transfer.c (top level): Add prototypes for us_read, us_write, next_record_r_unf and next_record_w_unf. (read_block_direct): Separate codepaths for unformatted direct and unformatted sequential. If a recl has been set by the user, use the number of bytes left for the record if it is smaller than the read request. Loop over subrecords. Set an error if the user has set a recl and the read was short. (write_buf): Separate codepaths for unformatted direct and unformatted sequential. If a recl has been set by the user, use the number of bytes left for the record if it is smaller than the read request. Loop over subrecords. Set an error if the user has set a recl and the read was short. (us_read): Add parameter continued (to indicate that bytes_left should not be intialized). Change default of record marker size to four bytes. Use subrecord. If the subrecord length is smaller than zero, this indicates a continuation. (us_write): Add parameter continued (to indicate that the continued flag should be set). Use subrecord. (pre_position): Use 0 for continued on us_write and us_read calls. (skip_record): New function. (next_record_r_unf): New function. (next_record_r): Use next_record_r_unf. (write_us_marker): Default size for record markers is four bytes. (next_record_w_unf): New function. (next_record_w): Use next_record_w_unf. From-SVN: r119412
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fortran/ChangeLog17
-rw-r--r--gcc/fortran/gfortran.h5
-rw-r--r--gcc/fortran/invoke.texi18
-rw-r--r--gcc/fortran/lang.opt4
-rw-r--r--gcc/fortran/options.c9
-rw-r--r--gcc/fortran/trans-decl.c17
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gfortran.dg/convert_implied_open.f908
-rw-r--r--gcc/testsuite/gfortran.dg/unf_short_record_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/unformatted_subrecord_1.f9045
10 files changed, 121 insertions, 13 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 9442f68..be3e91e 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,20 @@
+2006-12-01 Thomas Koenig <Thomas.Koenig@online.de>
+
+ PR libfortran/29568
+ * gfortran.h (gfc_option_t): Add max_subrecord_length.
+ (top level): Define MAX_SUBRECORD_LENGTH.
+ * lang.opt: Add option -fmax-subrecord-length=.
+ * trans-decl.c: Add new function set_max_subrecord_length.
+ (gfc_generate_function_code): If we are within the main
+ program and max_subrecord_length has been set, call
+ set_max_subrecord_length.
+ * options.c (gfc_init_options): Add defaults for
+ max_subrecord_lenght, convert and record_marker.
+ (gfc_handle_option): Add handling for
+ -fmax_subrecord_length.
+ * invoke.texi: Document the new default for
+ -frecord-marker=<n>.
+
2006-11-28 Paul Thomas <pault@gcc.gnu.org>
PR fortran/29976
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 277cc78..9a18e7851 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -59,6 +59,9 @@ char *alloca ();
#define GFC_MAX_DIMENSIONS 7 /* Maximum dimensions in an array. */
#define GFC_LETTERS 26 /* Number of letters in the alphabet. */
+#define MAX_SUBRECORD_LENGTH 2147483639 /* 2**31-9 */
+
+
#define free(x) Use_gfc_free_instead_of_free()
#define gfc_is_whitespace(c) ((c==' ') || (c=='\t'))
@@ -1661,12 +1664,12 @@ typedef struct
int fshort_enums;
int convert;
int record_marker;
+ int max_subrecord_length;
}
gfc_option_t;
extern gfc_option_t gfc_option;
-
/* Constructor nodes for array and structure constructors. */
typedef struct gfc_constructor
{
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index c27218c..c4ee5d3 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -650,13 +650,17 @@ variable override the default specified by -fconvert.}
@cindex -frecord-marker=@var{length}
@item -frecord-marker=@var{length}
Specify the length of record markers for unformatted files.
-Valid values for @var{length} are 4 and 8. Default is whatever
-@code{off_t} is specified to be on that particular system.
-Note that specifying @var{length} as 4 limits the record
-length of unformatted files to 2 GB. This option does not
-extend the maximum possible record length on systems where
-@code{off_t} is a four_byte quantity.
-
+Valid values for @var{length} are 4 and 8. Default is 4.
+@emph{This is different from previous versions of gfortran},
+which specified a default record marker length of 8 on most
+systems. If you want to read or write files compatible
+with earlier versions of gfortran, use @samp{-frecord-marker=8}.
+
+@cindex -fmax-subrecord-length=@var{length}
+@item -fmax-subrecord-length=@var{length}
+Specify the maximum length for a subrecord. The maximum permitted
+value for length is 2147483639, which is also the default. Only
+really useful for use by the gfortran testsuite.
@end table
@node Code Gen Options
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 053f63b..ebd6b8d 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -189,6 +189,10 @@ fmax-identifier-length=
Fortran RejectNegative Joined UInteger
-fmax-identifier-length=<n> Maximum identifier length
+fmax-subrecord-length=
+Fortran RejectNegative Joined UInteger
+-fmax-subrecord-length=<n> Maximum length for subrecords
+
fmax-stack-var-size=
Fortran RejectNegative Joined UInteger
-fmax-stack-var-size=<n> Size in bytes of the largest array that will be put on the stack
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index f03319b..6ec8467 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -51,6 +51,9 @@ gfc_init_options (unsigned int argc ATTRIBUTE_UNUSED,
gfc_option.max_continue_fixed = 19;
gfc_option.max_continue_free = 39;
gfc_option.max_identifier_length = GFC_MAX_SYMBOL_LEN;
+ gfc_option.max_subrecord_length = 0;
+ gfc_option.convert = CONVERT_NATIVE;
+ gfc_option.record_marker = 0;
gfc_option.verbose = 0;
gfc_option.warn_aliasing = 0;
@@ -636,6 +639,12 @@ gfc_handle_option (size_t scode, const char *arg, int value)
case OPT_frecord_marker_8:
gfc_option.record_marker = 8;
break;
+
+ case OPT_fmax_subrecord_length_:
+ if (value > MAX_SUBRECORD_LENGTH)
+ gfc_fatal_error ("Maximum subrecord length cannot exceed %d", MAX_SUBRECORD_LENGTH);
+
+ gfc_option.max_subrecord_length = value;
}
return result;
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 1f3ab7d..270083f 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -94,6 +94,7 @@ tree gfor_fndecl_set_fpe;
tree gfor_fndecl_set_std;
tree gfor_fndecl_set_convert;
tree gfor_fndecl_set_record_marker;
+tree gfor_fndecl_set_max_subrecord_length;
tree gfor_fndecl_ctime;
tree gfor_fndecl_fdate;
tree gfor_fndecl_ttynam;
@@ -2379,6 +2380,10 @@ gfc_build_builtin_function_decls (void)
gfc_build_library_function_decl (get_identifier (PREFIX("set_record_marker")),
void_type_node, 1, gfc_c_int_type_node);
+ gfor_fndecl_set_max_subrecord_length =
+ gfc_build_library_function_decl (get_identifier (PREFIX("set_max_subrecord_length")),
+ void_type_node, 1, gfc_c_int_type_node);
+
gfor_fndecl_in_pack = gfc_build_library_function_decl (
get_identifier (PREFIX("internal_pack")),
pvoid_type_node, 1, pvoid_type_node);
@@ -3187,6 +3192,18 @@ gfc_generate_function_code (gfc_namespace * ns)
}
+ if (sym->attr.is_main_program && gfc_option.max_subrecord_length != 0)
+ {
+ tree arglist, gfc_c_int_type_node;
+
+ gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind);
+ arglist = gfc_chainon_list (NULL_TREE,
+ build_int_cst (gfc_c_int_type_node,
+ gfc_option.max_subrecord_length));
+ tmp = build_function_call_expr (gfor_fndecl_set_max_subrecord_length, arglist);
+ gfc_add_expr_to_block (&body, tmp);
+ }
+
if (TREE_TYPE (DECL_RESULT (fndecl)) != void_type_node
&& sym->attr.subroutine)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 08b4e04..fe29e86 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2006-12-01 Thomas Koenig <Thomas.Koenig@online.de>
+
+ PR libfortran/29568
+ * gfortran.dg/convert_implied_open.f90: Change to
+ new default record length.
+ * gfortran.dg/unf_short_record_1.f90: Adapt to
+ new error message.
+ * gfortran.dg/unformatted_subrecords_1.f90: New test.
+
2006-12-01 Andrew MacLeod <amacleod@redhat.com>
* gcc.dg/max-1.c: Remove reference to -fno-tree-lrs option.
diff --git a/gcc/testsuite/gfortran.dg/convert_implied_open.f90 b/gcc/testsuite/gfortran.dg/convert_implied_open.f90
index 4066f61..9c25b5d 100644
--- a/gcc/testsuite/gfortran.dg/convert_implied_open.f90
+++ b/gcc/testsuite/gfortran.dg/convert_implied_open.f90
@@ -3,13 +3,13 @@
! PR 26735 - implied open didn't use to honor -fconvert
program main
implicit none
- integer (kind=8) :: i1, i2, i3
- write (10) 1_8
+ integer (kind=4) :: i1, i2, i3
+ write (10) 1_4
close (10)
- open (10, form="unformatted", access="direct", recl=8)
+ open (10, form="unformatted", access="direct", recl=4)
read (10,rec=1) i1
read (10,rec=2) i2
read (10,rec=3) i3
- if (i1 /= 8 .or. i2 /= 1 .or. i3 /= 8) call abort
+ if (i1 /= 4 .or. i2 /= 1 .or. i3 /= 4) call abort
close (10,status="delete")
end program main
diff --git a/gcc/testsuite/gfortran.dg/unf_short_record_1.f90 b/gcc/testsuite/gfortran.dg/unf_short_record_1.f90
index 1bb6273..45c94c2 100644
--- a/gcc/testsuite/gfortran.dg/unf_short_record_1.f90
+++ b/gcc/testsuite/gfortran.dg/unf_short_record_1.f90
@@ -11,7 +11,7 @@ program main
read (10, err=20, iomsg=msg) a
call abort
20 continue
- if (msg .ne. "Short record on unformatted read") call abort
+ if (msg .ne. "I/O past end of record on unformatted file") call abort
if (a(1) .ne. 'a' .or. a(2) .ne. 'b' .or. a(3) .ne. 'b') call abort
close (10, status="delete")
end program main
diff --git a/gcc/testsuite/gfortran.dg/unformatted_subrecord_1.f90 b/gcc/testsuite/gfortran.dg/unformatted_subrecord_1.f90
new file mode 100644
index 0000000..5812a8e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unformatted_subrecord_1.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+! { dg-options "-fmax-subrecord-length=16" }
+! Test Intel record markers with 16-byte subrecord sizes.
+program main
+ implicit none
+ integer, dimension(20) :: n
+ integer, dimension(30) :: m
+ integer :: i
+ real :: r
+ integer :: k
+ ! Maximum subrecord length is 16 here, or the test will fail.
+ open (10, file="f10.dat", &
+ form="unformatted", access="sequential")
+ n = (/ (i**2, i=1, 20) /)
+ write (10) n
+ close (10)
+ ! Read back the file, including record markers.
+ open (10, file="f10.dat", form="unformatted", access="stream")
+ read (10) m
+ if (any(m .ne. (/ -16, 1, 4, 9, 16, 16, -16, 25, 36, 49, 64, &
+ -16, -16, 81, 100, 121, 144, -16, -16, 169, 196, 225, &
+ 256, -16, 16, 289, 324, 361, 400, -16 /))) call abort
+ close (10)
+ open (10, file="f10.dat", form="unformatted", &
+ access="sequential")
+ m = 42
+ read (10) m(1:5)
+ if (any(m(1:5) .ne. (/ 1, 4, 9, 16, 25 /))) call abort
+ if (any(m(6:30) .ne. 42)) call abort
+ backspace 10
+ n = 0
+ read (10) n(1:5)
+ if (any(n(1:5) .ne. (/ 1, 4, 9, 16, 25 /))) call abort
+ if (any(n(6:20) .ne. 0)) call abort
+ ! Append to the end of the file
+ write (10) 3.14
+ ! Test multiple backspace statements
+ backspace 10
+ backspace 10
+ read (10) k
+ if (k .ne. 1) call abort
+ read (10) r
+ if (abs(r-3.14) .gt. 1e-7) call abort
+ close (10, status="delete")
+end program main