Commit dcfddbd4 by Jerry DeLisle

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
parent 9ad55c33
2009-06-07 Jerry DeLisle <jvdelisle@gcc.gnu.org> 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 PR libfortran/40334
* io/list_read.c (list_formatted_read_scalar): Set the end file * io/list_read.c (list_formatted_read_scalar): Set the end file
conditions after a return from EOF error. conditions after a return from EOF error.
......
...@@ -297,6 +297,7 @@ typedef struct ...@@ -297,6 +297,7 @@ typedef struct
CHARACTER2 (round); CHARACTER2 (round);
CHARACTER1 (sign); CHARACTER1 (sign);
CHARACTER2 (asynchronous); CHARACTER2 (asynchronous);
GFC_INTEGER_4 *newunit;
} }
st_parameter_open; st_parameter_open;
...@@ -794,6 +795,10 @@ internal_proto(unpack_filename); ...@@ -794,6 +795,10 @@ internal_proto(unpack_filename);
extern gfc_offset max_offset; extern gfc_offset max_offset;
internal_proto(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. */ /* Unit tree root. */
extern gfc_unit *unit_root; extern gfc_unit *unit_root;
internal_proto(unit_root); internal_proto(unit_root);
...@@ -831,6 +836,9 @@ internal_proto (finish_last_advance_record); ...@@ -831,6 +836,9 @@ internal_proto (finish_last_advance_record);
extern int unit_truncate (gfc_unit *, gfc_offset, st_parameter_common *); extern int unit_truncate (gfc_unit *, gfc_offset, st_parameter_common *);
internal_proto (unit_truncate); internal_proto (unit_truncate);
extern GFC_INTEGER_4 get_unique_unit_number (st_parameter_open *);
internal_proto(get_unique_unit_number);
/* open.c */ /* open.c */
extern gfc_unit *new_unit (st_parameter_open *, gfc_unit *, unit_flags *); extern gfc_unit *new_unit (st_parameter_open *, gfc_unit *, unit_flags *);
......
...@@ -814,7 +814,7 @@ st_open (st_parameter_open *opp) ...@@ -814,7 +814,7 @@ st_open (st_parameter_open *opp)
flags.convert = conv; 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, generate_error (&opp->common, LIBERROR_BAD_OPTION,
"Bad unit number in OPEN statement"); "Bad unit number in OPEN statement");
...@@ -842,8 +842,13 @@ st_open (st_parameter_open *opp) ...@@ -842,8 +842,13 @@ st_open (st_parameter_open *opp)
if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK) 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) if (u->s == NULL)
{ {
u = new_unit (opp, u, &flags); u = new_unit (opp, u, &flags);
......
...@@ -2020,7 +2020,7 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag) ...@@ -2020,7 +2020,7 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
close_unit (dtp->u.p.current_unit); close_unit (dtp->u.p.current_unit);
dtp->u.p.current_unit = NULL; dtp->u.p.current_unit = NULL;
generate_error (&dtp->common, LIBERROR_BAD_OPTION, generate_error (&dtp->common, LIBERROR_BAD_OPTION,
"Bad unit number in OPEN statement"); "Bad unit number in statement");
return; return;
} }
memset (&u_flags, '\0', sizeof (u_flags)); memset (&u_flags, '\0', sizeof (u_flags));
......
...@@ -67,6 +67,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -67,6 +67,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Subroutines related to units */ /* Subroutines related to units */
GFC_INTEGER_4 next_available_newunit;
#define GFC_FIRST_NEWUNIT -10
#define CACHE_SIZE 3 #define CACHE_SIZE 3
static gfc_unit *unit_cache[CACHE_SIZE]; static gfc_unit *unit_cache[CACHE_SIZE];
...@@ -131,7 +133,6 @@ rotate_right (gfc_unit * t) ...@@ -131,7 +133,6 @@ rotate_right (gfc_unit * t)
} }
static int static int
compare (int a, int b) compare (int a, int b)
{ {
...@@ -480,7 +481,7 @@ free_internal_unit (st_parameter_dt *dtp) ...@@ -480,7 +481,7 @@ free_internal_unit (st_parameter_dt *dtp)
/* get_unit()-- Returns the unit structure associated with the integer /* get_unit()-- Returns the unit structure associated with the integer
* unit or the internal file. */ unit or the internal file. */
gfc_unit * gfc_unit *
get_unit (st_parameter_dt *dtp, int do_create) get_unit (st_parameter_dt *dtp, int do_create)
...@@ -489,7 +490,7 @@ 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) if ((dtp->common.flags & IOPARM_DT_HAS_INTERNAL_UNIT) != 0)
return get_internal_unit(dtp); 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->u.p.unit_is_internal = 0;
dtp->internal_unit_desc = NULL; dtp->internal_unit_desc = NULL;
...@@ -499,7 +500,7 @@ get_unit (st_parameter_dt *dtp, int do_create) ...@@ -499,7 +500,7 @@ get_unit (st_parameter_dt *dtp, int do_create)
/*************************/ /*************************/
/* Initialize everything */ /* Initialize everything. */
void void
init_units (void) init_units (void)
...@@ -511,6 +512,8 @@ init_units (void) ...@@ -511,6 +512,8 @@ init_units (void)
__GTHREAD_MUTEX_INIT_FUNCTION (&unit_lock); __GTHREAD_MUTEX_INIT_FUNCTION (&unit_lock);
#endif #endif
next_available_newunit = GFC_FIRST_NEWUNIT;
if (options.stdin_unit >= 0) if (options.stdin_unit >= 0)
{ /* STDIN */ { /* STDIN */
u = insert_unit (options.stdin_unit); u = insert_unit (options.stdin_unit);
...@@ -601,10 +604,8 @@ init_units (void) ...@@ -601,10 +604,8 @@ init_units (void)
} }
/* Calculate the maximum file offset in a portable manner. /* Calculate the maximum file offset in a portable manner.
* max will be the largest signed number for the type gfc_offset. 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. */
* set a 1 in the LSB and keep a running sum, stopping at MSB-1 bit. */
max_offset = 0; max_offset = 0;
for (i = 0; i < sizeof (max_offset) * 8 - 1; i++) for (i = 0; i < sizeof (max_offset) * 8 - 1; i++)
max_offset = max_offset + ((gfc_offset) 1 << i); max_offset = max_offset + ((gfc_offset) 1 << i);
...@@ -663,8 +664,8 @@ unlock_unit (gfc_unit *u) ...@@ -663,8 +664,8 @@ unlock_unit (gfc_unit *u)
} }
/* close_unit()-- Close a unit. The stream is closed, and any memory /* close_unit()-- Close a unit. The stream is closed, and any memory
* associated with the stream is freed. Returns nonzero on I/O error. associated with the stream is freed. Returns nonzero on I/O error.
* Should be called with the u->lock locked. */ Should be called with the u->lock locked. */
int int
close_unit (gfc_unit *u) close_unit (gfc_unit *u)
...@@ -674,11 +675,11 @@ close_unit (gfc_unit *u) ...@@ -674,11 +675,11 @@ close_unit (gfc_unit *u)
/* close_units()-- Delete units on completion. We just keep deleting /* close_units()-- Delete units on completion. We just keep deleting
* the root of the treap until there is nothing left. the root of the treap until there is nothing left.
* Not sure what to do with locking here. Some other thread might be Not sure what to do with locking here. Some other thread might be
* holding some unit's lock and perhaps hold it indefinitely holding some unit's lock and perhaps hold it indefinitely
* (e.g. waiting for input from some pipe) and close_units shouldn't (e.g. waiting for input from some pipe) and close_units shouldn't
* delay the program too much. */ delay the program too much. */
void void
close_units (void) close_units (void)
...@@ -813,3 +814,22 @@ finish_last_advance_record (gfc_unit *u) ...@@ -813,3 +814,22 @@ finish_last_advance_record (gfc_unit *u)
fbuf_flush (u, u->mode); 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;
}
...@@ -590,6 +590,7 @@ st_parameter_common; ...@@ -590,6 +590,7 @@ st_parameter_common;
#define IOPARM_OPEN_HAS_ROUND (1 << 20) #define IOPARM_OPEN_HAS_ROUND (1 << 20)
#define IOPARM_OPEN_HAS_SIGN (1 << 21) #define IOPARM_OPEN_HAS_SIGN (1 << 21)
#define IOPARM_OPEN_HAS_ASYNCHRONOUS (1 << 22) #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 /* library start function and end macro. These can be expanded if needed
in the future. cmp is st_parameter_common *cmp */ in the future. cmp is st_parameter_common *cmp */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment