summaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authortkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>2005-12-10 20:01:56 +0000
committertkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>2005-12-10 20:01:56 +0000
commit9e94d29ff8bc21a0613f36a8b1754decbbb329d8 (patch)
treea3d754eebe0bc2166ffe8c241b2d9dfdd1098340 /gcc/fortran
parent7753ca4bd933e9abc902d48e81bc105ac1b70478 (diff)
downloadgcc-9e94d29ff8bc21a0613f36a8b1754decbbb329d8.tar.gz
2005-12-10 Thomas Koenig <Thomas.Koenig@online.de>
PR fortran/23815 * io.c (top level): Add convert to io_tag. (resolve_tag): convert is GFC_STD_GNU. (match_open_element): Add convert. (gfc_free_open): Likewise. (gfc_resolve_open): Likewise. (gfc_free_inquire): Likewise. (match_inquire_element): Likewise. * dump-parse-tree.c (gfc_show_code_node): Add convet for open and inquire. gfortran.h: Add convert to gfc_open and gfc_inquire. * trans-io.c (gfc_trans_open): Add convert. (gfc_trans_inquire): Likewise. * ioparm.def: Add convert to open and inquire. * gfortran.texi: Document CONVERT. 2005-12-10 Thomas Koenig <Thomas.Koenig@online.de> PR fortran/23815 * io/file_pos.c (unformatted_backspace): If flags.convert does not equal CONVERT_NATIVE, reverse the record marker. * io/open.c: Add convert_opt[]. (st_open): If no convert option is given, set CONVERT_NATIVE. If CONVERT_BIG or CONVERT_LITTLE are given, set flags.convert to CONVERT_NATIVE or CONVERT_SWAP (depending on wether we have a big- or little-endian system). * io/transfer.c (unformatted_read): Remove unused attribute from arguments. If we need to reverse bytes, break up large transfers into a loop. Split complex numbers into its two parts. (unformatted_write): Likewise. (us_read): If flags.convert does not equal CONVERT_NATIVE, reverse the record marker. (next_record_w): Likewise. (reverse_memcpy): New function. * io/inquire.c (inquire_via_unit): Implement convert. * io/io.h (top level): Add enum unit_convert. Add convert to st_parameter_open and st_parameter_inquire. Define IOPARM_OPEN_HAS_CONVERT and IOPARM_INQUIRE_HAS_CONVERT. Increase padding for st_parameter_dt. Declare reverse_memcpy(). 2005-12-10 Thomas Koenig <Thomas.Koenig@online.de> PR fortran/23815 * gfortran.dg/unf_io_convert_1.f90: New test. * gfortran.dg/unf_io_convert_2.f90: New test. * gfortran.dg/unf_io_convert_3.f90: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@108358 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog18
-rw-r--r--gcc/fortran/dump-parse-tree.c10
-rw-r--r--gcc/fortran/gfortran.h4
-rw-r--r--gcc/fortran/gfortran.texi37
-rw-r--r--gcc/fortran/io.c15
-rw-r--r--gcc/fortran/ioparm.def2
-rw-r--r--gcc/fortran/trans-io.c8
7 files changed, 92 insertions, 2 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 58cf367f1c8..e9a8f308dae 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,21 @@
+2005-12-10 Thomas Koenig <Thomas.Koenig@online.de>
+
+ PR fortran/23815
+ * io.c (top level): Add convert to io_tag.
+ (resolve_tag): convert is GFC_STD_GNU.
+ (match_open_element): Add convert.
+ (gfc_free_open): Likewise.
+ (gfc_resolve_open): Likewise.
+ (gfc_free_inquire): Likewise.
+ (match_inquire_element): Likewise.
+ * dump-parse-tree.c (gfc_show_code_node): Add
+ convet for open and inquire.
+ gfortran.h: Add convert to gfc_open and gfc_inquire.
+ * trans-io.c (gfc_trans_open): Add convert.
+ (gfc_trans_inquire): Likewise.
+ * ioparm.def: Add convert to open and inquire.
+ * gfortran.texi: Document CONVERT.
+
2005-12-09 Roger Sayle <roger@eyesopen.com>
PR fortran/22527
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 499e1fa22e5..ef5c88a94b4 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1148,6 +1148,11 @@ gfc_show_code_node (int level, gfc_code * c)
gfc_status (" PAD=");
gfc_show_expr (open->pad);
}
+ if (open->convert)
+ {
+ gfc_status (" CONVERT=");
+ gfc_show_expr (open->convert);
+ }
if (open->err != NULL)
gfc_status (" ERR=%d", open->err->value);
@@ -1349,6 +1354,11 @@ gfc_show_code_node (int level, gfc_code * c)
gfc_status (" PAD=");
gfc_show_expr (i->pad);
}
+ if (i->convert)
+ {
+ gfc_status (" CONVERT=");
+ gfc_show_expr (i->convert);
+ }
if (i->err != NULL)
gfc_status (" ERR=%d", i->err->value);
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 83de2675489..f22f6a48ab6 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1309,7 +1309,7 @@ gfc_alloc;
typedef struct
{
gfc_expr *unit, *file, *status, *access, *form, *recl,
- *blank, *position, *action, *delim, *pad, *iostat, *iomsg;
+ *blank, *position, *action, *delim, *pad, *iostat, *iomsg, *convert;
gfc_st_label *err;
}
gfc_open;
@@ -1336,7 +1336,7 @@ typedef struct
gfc_expr *unit, *file, *iostat, *exist, *opened, *number, *named,
*name, *access, *sequential, *direct, *form, *formatted,
*unformatted, *recl, *nextrec, *blank, *position, *action, *read,
- *write, *readwrite, *delim, *pad, *iolength, *iomsg;
+ *write, *readwrite, *delim, *pad, *iolength, *iomsg, *convert;
gfc_st_label *err;
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 92a6d5f4593..ea3ac245aa5 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -587,6 +587,7 @@ of extensions, and @option{-std=legacy} allows both without warning.
* Implicitly interconvert LOGICAL and INTEGER::
* Hollerith constants support::
* Cray pointers::
+* CONVERT specifier::
@end menu
@node Old-style kind specifications
@@ -930,6 +931,42 @@ pointees are passed as arguments, they are treated as ordinary
variables in the invoked function. Subsequent changes to the pointer
will not change the base address of the array that was passed.
+@node CONVERT specifier
+@section CONVERT specifier
+@cindex CONVERT specifier
+
+gfortran allows the conversion of unformatted data between little-
+and big-endian representation to facilitate moving of data
+between different systems. The conversion is indicated with
+the @code{CONVERT} specifier on the @code{OPEN} statement.
+
+Valid values for @code{CONVERT} are:
+@itemize @w{}
+@item @code{CONVERT='NATIVE'} Use the native format. This is the default.
+@item @code{CONVERT='SWAP'} Swap between little- and big-endian.
+@item @code{CONVERT='LITTLE_ENDIAN'} Use the little-endian format
+ for unformatted files.
+@item @code{CONVERT='BIG_ENDIAN'} Use the big-endian format for
+ unformatted files.
+@end itemize
+
+Using the option could look like this:
+@smallexample
+ open(file='big.dat',form='unformatted',access='sequential', &
+ convert='big_endian')
+@end smallexample
+
+The value of the conversion can be queried by using
+@code{INQUIRE(CONVERT=ch)}. The values returned are
+@code{'BIG_ENDIAN'} and @code{'LITTLE_ENDIAN'}.
+
+@code{CONVERT} works between big- and little-endian for
+@code{INTEGER} values of all supported kinds and for @code{REAL}
+on IEEE sytems of kinds 4 and 8. Conversion between different
+``extended double'' types on different architectures such as
+m68k and x86_64, which gfortran
+supports as @code{REAL(KIND=10)} will probably not work.
+
@c ---------------------------------------------------------------------
@include intrinsic.texi
@c ---------------------------------------------------------------------
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
index 6adc1efb613..090f905ea30 100644
--- a/gcc/fortran/io.c
+++ b/gcc/fortran/io.c
@@ -78,6 +78,7 @@ static const io_tag
tag_s_delim = {"DELIM", " delim = %v", BT_CHARACTER},
tag_s_pad = {"PAD", " pad = %v", BT_CHARACTER},
tag_iolength = {"IOLENGTH", " iolength = %v", BT_INTEGER},
+ tag_convert = {"CONVERT", " convert = %e", BT_CHARACTER},
tag_err = {"ERR", " err = %l", BT_UNKNOWN},
tag_end = {"END", " end = %l", BT_UNKNOWN},
tag_eor = {"EOR", " eor = %l", BT_UNKNOWN};
@@ -1051,6 +1052,12 @@ resolve_tag (const io_tag * tag, gfc_expr * e)
&e->where) == FAILURE)
return FAILURE;
}
+ if (tag == &tag_convert)
+ {
+ if (gfc_notify_std (GFC_STD_GNU, "Extension: CONVERT tag at %L",
+ &e->where) == FAILURE)
+ return FAILURE;
+ }
}
return SUCCESS;
@@ -1106,6 +1113,9 @@ match_open_element (gfc_open * open)
m = match_ltag (&tag_err, &open->err);
if (m != MATCH_NO)
return m;
+ m = match_etag (&tag_convert, &open->convert);
+ if (m != MATCH_NO)
+ return m;
return MATCH_NO;
}
@@ -1133,6 +1143,7 @@ gfc_free_open (gfc_open * open)
gfc_free_expr (open->action);
gfc_free_expr (open->delim);
gfc_free_expr (open->pad);
+ gfc_free_expr (open->convert);
gfc_free (open);
}
@@ -1158,6 +1169,7 @@ gfc_resolve_open (gfc_open * open)
RESOLVE_TAG (&tag_e_action, open->action);
RESOLVE_TAG (&tag_e_delim, open->delim);
RESOLVE_TAG (&tag_e_pad, open->pad);
+ RESOLVE_TAG (&tag_convert, open->convert);
if (gfc_reference_st_label (open->err, ST_LABEL_TARGET) == FAILURE)
return FAILURE;
@@ -2438,6 +2450,7 @@ gfc_free_inquire (gfc_inquire * inquire)
gfc_free_expr (inquire->delim);
gfc_free_expr (inquire->pad);
gfc_free_expr (inquire->iolength);
+ gfc_free_expr (inquire->convert);
gfc_free (inquire);
}
@@ -2479,6 +2492,7 @@ match_inquire_element (gfc_inquire * inquire)
RETM m = match_vtag (&tag_s_delim, &inquire->delim);
RETM m = match_vtag (&tag_s_pad, &inquire->pad);
RETM m = match_vtag (&tag_iolength, &inquire->iolength);
+ RETM m = match_vtag (&tag_convert, &inquire->convert);
RETM return MATCH_NO;
}
@@ -2632,6 +2646,7 @@ gfc_resolve_inquire (gfc_inquire * inquire)
RESOLVE_TAG (&tag_s_delim, inquire->delim);
RESOLVE_TAG (&tag_s_pad, inquire->pad);
RESOLVE_TAG (&tag_iolength, inquire->iolength);
+ RESOLVE_TAG (&tag_convert, inquire->convert);
if (gfc_reference_st_label (inquire->err, ST_LABEL_TARGET) == FAILURE)
return FAILURE;
diff --git a/gcc/fortran/ioparm.def b/gcc/fortran/ioparm.def
index 9ca0cf659b1..0fe9a7b45bf 100644
--- a/gcc/fortran/ioparm.def
+++ b/gcc/fortran/ioparm.def
@@ -25,6 +25,7 @@ IOPARM (open, position, 1 << 13, char1)
IOPARM (open, action, 1 << 14, char2)
IOPARM (open, delim, 1 << 15, char1)
IOPARM (open, pad, 1 << 16, char2)
+IOPARM (open, convert, 1 << 17, char1)
IOPARM (close, common, 0, common)
IOPARM (close, status, 1 << 7, char1)
IOPARM (filepos, common, 0, common)
@@ -51,6 +52,7 @@ IOPARM (inquire, unformatted, 1 << 25, char1)
IOPARM (inquire, read, 1 << 26, char2)
IOPARM (inquire, write, 1 << 27, char1)
IOPARM (inquire, readwrite, 1 << 28, char2)
+IOPARM (inquire, convert, 1 << 29, char1)
#ifndef IOPARM_dt_list_format
#define IOPARM_dt_list_format (1 << 7)
#define IOPARM_dt_namelist_read_mode (1 << 8)
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 98c1d1fcf8b..87a11c3d861 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -791,6 +791,10 @@ gfc_trans_open (gfc_code * code)
if (p->err)
mask |= IOPARM_common_err;
+ if (p->convert)
+ mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
+ p->convert);
+
set_parameter_const (&block, var, IOPARM_common_flags, mask);
tmp = gfc_build_addr_expr (NULL_TREE, var);
@@ -1073,6 +1077,10 @@ gfc_trans_inquire (gfc_code * code)
if (p->err)
mask |= IOPARM_common_err;
+ if (p->convert)
+ mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
+ p->convert);
+
set_parameter_const (&block, var, IOPARM_common_flags, mask);
tmp = gfc_build_addr_expr (NULL_TREE, var);