Index: gcc/libgfortran/io/unit.c |
diff --git a/gcc/libgfortran/io/unit.c b/gcc/libgfortran/io/unit.c |
index b69853783954cdadf84546f5c46e4d625f057ec2..3eb66e9d26d9eec42e29dd5a54f3be3dd4d5bd2b 100644 |
--- a/gcc/libgfortran/io/unit.c |
+++ b/gcc/libgfortran/io/unit.c |
@@ -24,6 +24,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
<http://www.gnu.org/licenses/>. */ |
#include "io.h" |
+#include "fbuf.h" |
+#include "format.h" |
+#include "unix.h" |
#include <stdlib.h> |
#include <string.h> |
@@ -67,6 +70,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 +136,6 @@ rotate_right (gfc_unit * t) |
} |
- |
static int |
compare (int a, int b) |
{ |
@@ -440,6 +444,7 @@ get_internal_unit (st_parameter_dt *dtp) |
iunit->flags.decimal = DECIMAL_POINT; |
iunit->flags.encoding = ENCODING_DEFAULT; |
iunit->flags.async = ASYNC_NO; |
+ iunit->flags.round = ROUND_COMPATIBLE; |
/* Initialize the data transfer parameters. */ |
@@ -480,7 +485,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 +494,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 +504,7 @@ get_unit (st_parameter_dt *dtp, int do_create) |
/*************************/ |
-/* Initialize everything */ |
+/* Initialize everything. */ |
void |
init_units (void) |
@@ -511,6 +516,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); |
@@ -528,6 +535,7 @@ init_units (void) |
u->flags.decimal = DECIMAL_POINT; |
u->flags.encoding = ENCODING_DEFAULT; |
u->flags.async = ASYNC_NO; |
+ u->flags.round = ROUND_COMPATIBLE; |
u->recl = options.default_recl; |
u->endfile = NO_ENDFILE; |
@@ -557,6 +565,7 @@ init_units (void) |
u->flags.decimal = DECIMAL_POINT; |
u->flags.encoding = ENCODING_DEFAULT; |
u->flags.async = ASYNC_NO; |
+ u->flags.round = ROUND_COMPATIBLE; |
u->recl = options.default_recl; |
u->endfile = AT_ENDFILE; |
@@ -586,6 +595,7 @@ init_units (void) |
u->flags.decimal = DECIMAL_POINT; |
u->flags.encoding = ENCODING_DEFAULT; |
u->flags.async = ASYNC_NO; |
+ u->flags.round = ROUND_COMPATIBLE; |
u->recl = options.default_recl; |
u->endfile = AT_ENDFILE; |
@@ -601,10 +611,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); |
@@ -638,6 +646,7 @@ close_unit_1 (gfc_unit *u, int locked) |
u->file = NULL; |
u->file_len = 0; |
+ free_format_hash_table (u); |
fbuf_destroy (u); |
if (!locked) |
@@ -662,8 +671,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) |
@@ -673,11 +682,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) |
@@ -812,3 +821,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; |
+} |