| 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;
|
| +}
|
|
|