aboutsummaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorJerry DeLisle <jvdelisle@gcc.gnu.org>2009-06-07 19:00:47 +0000
committerJerry DeLisle <jvdelisle@gcc.gnu.org>2009-06-07 19:00:47 +0000
commitdcfddbd49c64dc1e8b57e3abe1b941bdd74b8f70 (patch)
treea644300144767eca9a438e4638477cda691850c5 /libgfortran
parent9ad55c33ae2d0c410fbc563fd59e8edb37a48b8b (diff)
downloadgcc-dcfddbd49c64dc1e8b57e3abe1b941bdd74b8f70.zip
gcc-dcfddbd49c64dc1e8b57e3abe1b941bdd74b8f70.tar.gz
gcc-dcfddbd49c64dc1e8b57e3abe1b941bdd74b8f70.tar.bz2
re PR fortran/40008 (F2008: Add NEWUNIT= for OPEN statement)
2009-06-07 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR libfortran/40008 * libgfortran.h: Define IOPARM_OPEN_HAS_NEWUNIT. * io/open.c (st_open): Don't error on negative unit number if NEWUNIT was specified. If NEWUNIT is specified, call new function to get the unique unit number and assign it. * io/io.h (st_parameter_open): Add pointer to newunit. Add prototype for next_available_newunit. Add prototype for new function, get_unique_unit_number. * io/unit.c: Declare next_available_newunit. Define the first newunit number. (init_units): Initialize next_available_unit. (get_unique_unit_number): New function. Fix whitespace and comments. * io/transfer.c (data_transfer_init): Update error message to not be specific to OPEN statements. From-SVN: r148253
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog16
-rw-r--r--libgfortran/io/io.h8
-rw-r--r--libgfortran/io/open.c9
-rw-r--r--libgfortran/io/transfer.c2
-rw-r--r--libgfortran/io/unit.c50
-rw-r--r--libgfortran/libgfortran.h1
6 files changed, 68 insertions, 18 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 6558936..1377d68 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,5 +1,21 @@
2009-06-07 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+ PR libfortran/40008
+ * libgfortran.h: Define IOPARM_OPEN_HAS_NEWUNIT.
+ * io/open.c (st_open): Don't error on negative unit number if NEWUNIT
+ was specified. If NEWUNIT is specified, call new function to get the
+ unique unit number and assign it.
+ * io/io.h (st_parameter_open): Add pointer to newunit. Add prototype for
+ next_available_newunit. Add prototype for new function,
+ get_unique_unit_number.
+ * io/unit.c: Declare next_available_newunit. Define the first newunit
+ number. (init_units): Initialize next_available_unit.
+ (get_unique_unit_number): New function. Fix whitespace and comments.
+ * io/transfer.c (data_transfer_init): Update error message to not be
+ specific to OPEN statements.
+
+2009-06-07 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
PR libfortran/40334
* io/list_read.c (list_formatted_read_scalar): Set the end file
conditions after a return from EOF error.
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 22e097a..9e1e45e 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -297,6 +297,7 @@ typedef struct
CHARACTER2 (round);
CHARACTER1 (sign);
CHARACTER2 (asynchronous);
+ GFC_INTEGER_4 *newunit;
}
st_parameter_open;
@@ -794,6 +795,10 @@ internal_proto(unpack_filename);
extern gfc_offset max_offset;
internal_proto(max_offset);
+/* Unit number to be assigned when NEWUNIT is used in an OPEN statement. */
+extern GFC_INTEGER_4 next_available_newunit;
+internal_proto(next_available_newunit);
+
/* Unit tree root. */
extern gfc_unit *unit_root;
internal_proto(unit_root);
@@ -831,6 +836,9 @@ internal_proto (finish_last_advance_record);
extern int unit_truncate (gfc_unit *, gfc_offset, st_parameter_common *);
internal_proto (unit_truncate);
+extern GFC_INTEGER_4 get_unique_unit_number (st_parameter_open *);
+internal_proto(get_unique_unit_number);
+
/* open.c */
extern gfc_unit *new_unit (st_parameter_open *, gfc_unit *, unit_flags *);
diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c
index ba6e9d8..d5b4007 100644
--- a/libgfortran/io/open.c
+++ b/libgfortran/io/open.c
@@ -814,7 +814,7 @@ st_open (st_parameter_open *opp)
flags.convert = conv;
- if (opp->common.unit < 0)
+ if (!(opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT) && opp->common.unit < 0)
generate_error (&opp->common, LIBERROR_BAD_OPTION,
"Bad unit number in OPEN statement");
@@ -842,8 +842,13 @@ st_open (st_parameter_open *opp)
if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
{
- u = find_or_create_unit (opp->common.unit);
+ if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT))
+ {
+ *opp->newunit = get_unique_unit_number(opp);
+ opp->common.unit = *opp->newunit;
+ }
+ u = find_or_create_unit (opp->common.unit);
if (u->s == NULL)
{
u = new_unit (opp, u, &flags);
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index ea1ef7a..08ba7f5 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -2020,7 +2020,7 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
close_unit (dtp->u.p.current_unit);
dtp->u.p.current_unit = NULL;
generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "Bad unit number in OPEN statement");
+ "Bad unit number in statement");
return;
}
memset (&u_flags, '\0', sizeof (u_flags));
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index 77afd9b..d8d0c29 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -67,6 +67,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Subroutines related to units */
+GFC_INTEGER_4 next_available_newunit;
+#define GFC_FIRST_NEWUNIT -10
#define CACHE_SIZE 3
static gfc_unit *unit_cache[CACHE_SIZE];
@@ -131,7 +133,6 @@ rotate_right (gfc_unit * t)
}
-
static int
compare (int a, int b)
{
@@ -480,7 +481,7 @@ free_internal_unit (st_parameter_dt *dtp)
/* get_unit()-- Returns the unit structure associated with the integer
- * unit or the internal file. */
+ unit or the internal file. */
gfc_unit *
get_unit (st_parameter_dt *dtp, int do_create)
@@ -489,7 +490,7 @@ get_unit (st_parameter_dt *dtp, int do_create)
if ((dtp->common.flags & IOPARM_DT_HAS_INTERNAL_UNIT) != 0)
return get_internal_unit(dtp);
- /* Has to be an external unit */
+ /* Has to be an external unit. */
dtp->u.p.unit_is_internal = 0;
dtp->internal_unit_desc = NULL;
@@ -499,7 +500,7 @@ get_unit (st_parameter_dt *dtp, int do_create)
/*************************/
-/* Initialize everything */
+/* Initialize everything. */
void
init_units (void)
@@ -511,6 +512,8 @@ init_units (void)
__GTHREAD_MUTEX_INIT_FUNCTION (&unit_lock);
#endif
+ next_available_newunit = GFC_FIRST_NEWUNIT;
+
if (options.stdin_unit >= 0)
{ /* STDIN */
u = insert_unit (options.stdin_unit);
@@ -601,10 +604,8 @@ init_units (void)
}
/* Calculate the maximum file offset in a portable manner.
- * max will be the largest signed number for the type gfc_offset.
- *
- * set a 1 in the LSB and keep a running sum, stopping at MSB-1 bit. */
-
+ max will be the largest signed number for the type gfc_offset.
+ set a 1 in the LSB and keep a running sum, stopping at MSB-1 bit. */
max_offset = 0;
for (i = 0; i < sizeof (max_offset) * 8 - 1; i++)
max_offset = max_offset + ((gfc_offset) 1 << i);
@@ -663,8 +664,8 @@ unlock_unit (gfc_unit *u)
}
/* close_unit()-- Close a unit. The stream is closed, and any memory
- * associated with the stream is freed. Returns nonzero on I/O error.
- * Should be called with the u->lock locked. */
+ associated with the stream is freed. Returns nonzero on I/O error.
+ Should be called with the u->lock locked. */
int
close_unit (gfc_unit *u)
@@ -674,11 +675,11 @@ close_unit (gfc_unit *u)
/* close_units()-- Delete units on completion. We just keep deleting
- * the root of the treap until there is nothing left.
- * Not sure what to do with locking here. Some other thread might be
- * holding some unit's lock and perhaps hold it indefinitely
- * (e.g. waiting for input from some pipe) and close_units shouldn't
- * delay the program too much. */
+ the root of the treap until there is nothing left.
+ Not sure what to do with locking here. Some other thread might be
+ holding some unit's lock and perhaps hold it indefinitely
+ (e.g. waiting for input from some pipe) and close_units shouldn't
+ delay the program too much. */
void
close_units (void)
@@ -813,3 +814,22 @@ finish_last_advance_record (gfc_unit *u)
fbuf_flush (u, u->mode);
}
+/* Assign a negative number for NEWUNIT in OPEN statements. */
+GFC_INTEGER_4
+get_unique_unit_number (st_parameter_open *opp)
+{
+ GFC_INTEGER_4 num;
+
+ __gthread_mutex_lock (&unit_lock);
+ num = next_available_newunit--;
+
+ /* Do not allow NEWUNIT numbers to wrap. */
+ if (next_available_newunit >= GFC_FIRST_NEWUNIT )
+ {
+ __gthread_mutex_unlock (&unit_lock);
+ generate_error (&opp->common, LIBERROR_INTERNAL, "NEWUNIT exhausted");
+ return 0;
+ }
+ __gthread_mutex_unlock (&unit_lock);
+ return num;
+}
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 3591fa9..a2f3e06 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -590,6 +590,7 @@ st_parameter_common;
#define IOPARM_OPEN_HAS_ROUND (1 << 20)
#define IOPARM_OPEN_HAS_SIGN (1 << 21)
#define IOPARM_OPEN_HAS_ASYNCHRONOUS (1 << 22)
+#define IOPARM_OPEN_HAS_NEWUNIT (1 << 23)
/* library start function and end macro. These can be expanded if needed
in the future. cmp is st_parameter_common *cmp */