PR libfortran/25561 libfortran/37754
2009-03-22 Janne Blomqvist <jb@gcc.gnu.org> PR libfortran/25561 libfortran/37754 * io/io.h (struct stream): Define new stream interface function pointers, and inline functions for accessing it. (struct fbuf): Use int instead of size_t, remove flushed element. (mem_alloc_w): New prototype. (mem_alloc_r): New prototype. (stream_at_bof): Remove prototype. (stream_at_eof): Remove prototype. (file_position): Remove prototype. (flush): Remove prototype. (stream_offset): Remove prototype. (unit_truncate): New prototype. (read_block_form): Change to return pointer, int* argument. (hit_eof): New prototype. (fbuf_init): Change prototype. (fbuf_reset): Change prototype. (fbuf_alloc): Change prototype. (fbuf_flush): Change prototype. (fbuf_seek): Change prototype. (fbuf_read): New prototype. (fbuf_getc_refill): New prototype. (fbuf_getc): New inline function. * io/fbuf.c (fbuf_init): Use int, get rid of flushed. (fbuf_debug): New function. (fbuf_reset): Flush, and return position offset. (fbuf_alloc): Simplify, don't flush, just realloc. (fbuf_flush): Make usable for read mode, salvage remaining bytes. (fbuf_seek): New whence argument. (fbuf_read): New function. (fbuf_getc_refill): New function. * io/file_pos.c (formatted_backspace): Use new stream interface. (unformatted_backspace): Likewise. (st_backspace): Make sure format buffer is reset, use new stream interface, use unit_truncate. (st_endfile): Likewise. (st_rewind): Likewise. * io/intrinsics.c: Use new stream interface. * io/list_read.c (push_char): Don't use u.p.scratch, use realloc to resize. (free_saved): Don't check u.p.scratch. (next_char): Use new stream interface, use fbuf_getc() for external files. (finish_list_read): flush format buffer. (nml_query): Update to use modified interface:s * io/open.c (test_endfile): Use new stream interface. (edit_modes): Likewise. (new_unit): Likewise, set bytes_left to 1 for stream files. * io/read.c (read_l): Use new read_block_form interface. (read_utf8): Likewise. (read_utf8_char1): Likewise. (read_default_char1): Likewise. (read_utf8_char4): Likewise. (read_default_char4): Likewise. (read_a): Likewise. (read_a_char4): Likewise. (read_decimal): Likewise. (read_radix): Likewise. (read_f): Likewise. * io/transfer.c (read_sf): Use fbuf_read and mem_alloc_r, remove usage of u.p.line_buffer. (read_block_form): Update interface to return pointer, use fbuf_read for direct access. (read_block_direct): Update to new stream interface. (write_block): Use mem_alloc_w for internal I/O. (write_buf): Update to new stream interface. (formatted_transfer_scalar): Don't use u.p.line_buffer, use fbuf_seek for external files. (us_read): Update to new stream interface. (us_write): Likewise. (data_transfer_init): Always check if we switch modes and flush. (skip_record): Use new stream interface, fix comparison. (next_record_r): Check for and reset u.p.at_eof, use new stream interface, use fbuf_getc for spacing. (write_us_marker): Update to new stream interface, don't inline. (next_record_w_unf): Likewise. (sset): New function. (next_record_w): Use new stream interface, use fbuf for printing newline. (next_record): Use new stream interface. (finalize_transfer): Remove sfree call, use new stream interface. (st_iolength_done): Don't use u.p.scratch. (st_read): Don't check for end of file. (st_read_done): Don't use u.p.scratch, use unit_truncate. (hit_eof): New function. * io/unit.c (init_units): Always init fbuf for formatted units. (update_position): Use new stream interface. (unit_truncate): New function. (finish_last_advance_record): Use fbuf to print newline. * io/unix.c: Remove unused SSIZE_MAX macro. (BUFFER_SIZE): Make static const variable rather than macro. (struct unix_stream): Remove dirty_offset, len, method, small_buffer. Order elements by decreasing size. (struct int_stream): Remove. (move_pos_offset): Remove usage of dirty_offset. (reset_stream): Remove. (do_read): Rename to raw_read, update to match new stream interface. (do_write): Rename to raw_write, update to new stream interface. (raw_seek): New function. (raw_tell): New function. (raw_truncate): New function. (raw_close): New function. (raw_flush): New function. (raw_init): New function. (fd_alloc): Remove. (fd_alloc_r_at): Remove. (fd_alloc_w_at): Remove. (fd_sfree): Remove. (fd_seek): Remove. (fd_truncate): Remove. (fd_sset): Remove. (fd_read): Remove. (fd_write): Remove. (fd_close): Remove. (fd_open): Remove. (fd_flush): Rename to buf_flush, update to new stream interface and unix_stream. (buf_read): New function. (buf_write): New function. (buf_seek): New function. (buf_tell): New function. (buf_truncate): New function. (buf_close): New function. (buf_init): New function. (mem_alloc_r_at): Rename to mem_alloc_r, change prototype. (mem_alloc_w_at): Rename to mem_alloc_w, change prototype. (mem_read): Change to match new stream interface. (mem_write): Likewise. (mem_seek): Likewise. (mem_tell): Likewise. (mem_truncate): Likewise. (mem_close): Likewise. (mem_flush): New function. (mem_sfree): Remove. (empty_internal_buffer): Cast to correct type. (open_internal): Use correct type, init function pointers. (fd_to_stream): Test whether to open file as buffered or raw. (output_stream): Remove mode set. (error_stream): Likewise. (flush_all_units_1): Use new stream interface. (flush_all_units): Likewise. (stream_at_bof): Remove. (stream_at_eof): Remove. (file_position): Remove. (file_length): Update logic to use stream interface. (flush): Remove. (stream_offset): Remove. * io/write.c (write_utf8_char4): Use int instead of size_t. (write_x): Extra safety check. (namelist_write_newline): Use new stream interface. [[Split portion of a mixed commit.]] From-SVN: r144993.2
This commit is contained in:
parent
048fd7857b
commit
9e544d738a
4 changed files with 530 additions and 440 deletions
|
@ -49,34 +49,59 @@ struct st_parameter_dt;
|
|||
|
||||
typedef struct stream
|
||||
{
|
||||
char *(*alloc_w_at) (struct stream *, int *);
|
||||
try (*sfree) (struct stream *);
|
||||
try (*close) (struct stream *);
|
||||
try (*seek) (struct stream *, gfc_offset);
|
||||
try (*trunc) (struct stream *);
|
||||
int (*read) (struct stream *, void *, size_t *);
|
||||
int (*write) (struct stream *, const void *, size_t *);
|
||||
try (*set) (struct stream *, int, size_t);
|
||||
ssize_t (*read) (struct stream *, void *, ssize_t);
|
||||
ssize_t (*write) (struct stream *, const void *, ssize_t);
|
||||
off_t (*seek) (struct stream *, off_t, int);
|
||||
off_t (*tell) (struct stream *);
|
||||
int (*truncate) (struct stream *, off_t);
|
||||
int (*flush) (struct stream *);
|
||||
int (*close) (struct stream *);
|
||||
}
|
||||
stream;
|
||||
|
||||
typedef enum
|
||||
{ SYNC_BUFFERED, SYNC_UNBUFFERED, ASYNC }
|
||||
io_mode;
|
||||
/* Inline functions for doing file I/O given a stream. */
|
||||
static inline ssize_t
|
||||
sread (stream * s, void * buf, ssize_t nbyte)
|
||||
{
|
||||
return s->read (s, buf, nbyte);
|
||||
}
|
||||
|
||||
/* Macros for doing file I/O given a stream. */
|
||||
static inline ssize_t
|
||||
swrite (stream * s, const void * buf, ssize_t nbyte)
|
||||
{
|
||||
return s->write (s, buf, nbyte);
|
||||
}
|
||||
|
||||
#define sfree(s) ((s)->sfree)(s)
|
||||
#define sclose(s) ((s)->close)(s)
|
||||
static inline off_t
|
||||
sseek (stream * s, off_t offset, int whence)
|
||||
{
|
||||
return s->seek (s, offset, whence);
|
||||
}
|
||||
|
||||
#define salloc_w(s, len) ((s)->alloc_w_at)(s, len)
|
||||
static inline off_t
|
||||
stell (stream * s)
|
||||
{
|
||||
return s->tell (s);
|
||||
}
|
||||
|
||||
#define sseek(s, pos) ((s)->seek)(s, pos)
|
||||
#define struncate(s) ((s)->trunc)(s)
|
||||
#define sread(s, buf, nbytes) ((s)->read)(s, buf, nbytes)
|
||||
#define swrite(s, buf, nbytes) ((s)->write)(s, buf, nbytes)
|
||||
static inline int
|
||||
struncate (stream * s, off_t length)
|
||||
{
|
||||
return s->truncate (s, length);
|
||||
}
|
||||
|
||||
static inline int
|
||||
sflush (stream * s)
|
||||
{
|
||||
return s->flush (s);
|
||||
}
|
||||
|
||||
static inline int
|
||||
sclose (stream * s)
|
||||
{
|
||||
return s->close (s);
|
||||
}
|
||||
|
||||
#define sset(s, c, n) ((s)->set)(s, c, n)
|
||||
|
||||
/* Macros for testing what kinds of I/O we are doing. */
|
||||
|
||||
|
@ -538,10 +563,9 @@ unit_flags;
|
|||
typedef struct fbuf
|
||||
{
|
||||
char *buf; /* Start of buffer. */
|
||||
size_t len; /* Length of buffer. */
|
||||
size_t act; /* Active bytes in buffer. */
|
||||
size_t flushed; /* Flushed bytes from beginning of buffer. */
|
||||
size_t pos; /* Current position in buffer. */
|
||||
int len; /* Length of buffer. */
|
||||
int act; /* Active bytes in buffer. */
|
||||
int pos; /* Current position in buffer. */
|
||||
}
|
||||
fbuf;
|
||||
|
||||
|
@ -683,6 +707,12 @@ internal_proto(open_external);
|
|||
extern stream *open_internal (char *, int, gfc_offset);
|
||||
internal_proto(open_internal);
|
||||
|
||||
extern char * mem_alloc_w (stream *, int *);
|
||||
internal_proto(mem_alloc_w);
|
||||
|
||||
extern char * mem_alloc_r (stream *, int *);
|
||||
internal_proto(mem_alloc_w);
|
||||
|
||||
extern stream *input_stream (void);
|
||||
internal_proto(input_stream);
|
||||
|
||||
|
@ -698,12 +728,6 @@ internal_proto(compare_file_filename);
|
|||
extern gfc_unit *find_file (const char *file, gfc_charlen_type file_len);
|
||||
internal_proto(find_file);
|
||||
|
||||
extern int stream_at_bof (stream *);
|
||||
internal_proto(stream_at_bof);
|
||||
|
||||
extern int stream_at_eof (stream *);
|
||||
internal_proto(stream_at_eof);
|
||||
|
||||
extern int delete_file (gfc_unit *);
|
||||
internal_proto(delete_file);
|
||||
|
||||
|
@ -734,9 +758,6 @@ internal_proto(inquire_readwrite);
|
|||
extern gfc_offset file_length (stream *);
|
||||
internal_proto(file_length);
|
||||
|
||||
extern gfc_offset file_position (stream *);
|
||||
internal_proto(file_position);
|
||||
|
||||
extern int is_seekable (stream *);
|
||||
internal_proto(is_seekable);
|
||||
|
||||
|
@ -752,18 +773,12 @@ internal_proto(flush_if_preconnected);
|
|||
extern void empty_internal_buffer(stream *);
|
||||
internal_proto(empty_internal_buffer);
|
||||
|
||||
extern try flush (stream *);
|
||||
internal_proto(flush);
|
||||
|
||||
extern int stream_isatty (stream *);
|
||||
internal_proto(stream_isatty);
|
||||
|
||||
extern char * stream_ttyname (stream *);
|
||||
internal_proto(stream_ttyname);
|
||||
|
||||
extern gfc_offset stream_offset (stream *s);
|
||||
internal_proto(stream_offset);
|
||||
|
||||
extern int unpack_filename (char *, const char *, int);
|
||||
internal_proto(unpack_filename);
|
||||
|
||||
|
@ -807,6 +822,9 @@ internal_proto(update_position);
|
|||
extern void finish_last_advance_record (gfc_unit *u);
|
||||
internal_proto (finish_last_advance_record);
|
||||
|
||||
extern int unit_truncate (gfc_unit *, gfc_offset, st_parameter_common *);
|
||||
internal_proto (unit_truncate);
|
||||
|
||||
/* open.c */
|
||||
|
||||
extern gfc_unit *new_unit (st_parameter_open *, gfc_unit *, unit_flags *);
|
||||
|
@ -836,7 +854,7 @@ internal_proto(free_format_data);
|
|||
extern const char *type_name (bt);
|
||||
internal_proto(type_name);
|
||||
|
||||
extern try read_block_form (st_parameter_dt *, void *, size_t *);
|
||||
extern void * read_block_form (st_parameter_dt *, int *);
|
||||
internal_proto(read_block_form);
|
||||
|
||||
extern char *read_sf (st_parameter_dt *, int *, int);
|
||||
|
@ -862,6 +880,9 @@ internal_proto (reverse_memcpy);
|
|||
extern void st_wait (st_parameter_wait *);
|
||||
export_proto(st_wait);
|
||||
|
||||
extern void hit_eof (st_parameter_dt *);
|
||||
internal_proto(hit_eof);
|
||||
|
||||
/* read.c */
|
||||
|
||||
extern void set_integer (void *, GFC_INTEGER_LARGEST, int);
|
||||
|
@ -968,24 +989,39 @@ extern size_t size_from_complex_kind (int);
|
|||
internal_proto(size_from_complex_kind);
|
||||
|
||||
/* fbuf.c */
|
||||
extern void fbuf_init (gfc_unit *, size_t);
|
||||
extern void fbuf_init (gfc_unit *, int);
|
||||
internal_proto(fbuf_init);
|
||||
|
||||
extern void fbuf_destroy (gfc_unit *);
|
||||
internal_proto(fbuf_destroy);
|
||||
|
||||
extern void fbuf_reset (gfc_unit *);
|
||||
extern int fbuf_reset (gfc_unit *);
|
||||
internal_proto(fbuf_reset);
|
||||
|
||||
extern char * fbuf_alloc (gfc_unit *, size_t);
|
||||
extern char * fbuf_alloc (gfc_unit *, int);
|
||||
internal_proto(fbuf_alloc);
|
||||
|
||||
extern int fbuf_flush (gfc_unit *, int);
|
||||
extern int fbuf_flush (gfc_unit *, unit_mode);
|
||||
internal_proto(fbuf_flush);
|
||||
|
||||
extern int fbuf_seek (gfc_unit *, gfc_offset);
|
||||
extern int fbuf_seek (gfc_unit *, int, int);
|
||||
internal_proto(fbuf_seek);
|
||||
|
||||
extern char * fbuf_read (gfc_unit *, int *);
|
||||
internal_proto(fbuf_read);
|
||||
|
||||
/* Never call this function, only use fbuf_getc(). */
|
||||
extern int fbuf_getc_refill (gfc_unit *);
|
||||
internal_proto(fbuf_getc_refill);
|
||||
|
||||
static inline int
|
||||
fbuf_getc (gfc_unit * u)
|
||||
{
|
||||
if (u->fbuf->pos < u->fbuf->act)
|
||||
return (unsigned char) u->fbuf->buf[u->fbuf->pos++];
|
||||
return fbuf_getc_refill (u);
|
||||
}
|
||||
|
||||
/* lock.c */
|
||||
extern void free_ionml (st_parameter_dt *);
|
||||
internal_proto(free_ionml);
|
||||
|
|
|
@ -33,6 +33,7 @@ Boston, MA 02110-1301, USA. */
|
|||
|
||||
#include "io.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
|
@ -79,9 +80,8 @@ push_char (st_parameter_dt *dtp, char c)
|
|||
|
||||
if (dtp->u.p.saved_string == NULL)
|
||||
{
|
||||
if (dtp->u.p.scratch == NULL)
|
||||
dtp->u.p.scratch = get_mem (SCRATCH_SIZE);
|
||||
dtp->u.p.saved_string = dtp->u.p.scratch;
|
||||
dtp->u.p.saved_string = get_mem (SCRATCH_SIZE);
|
||||
// memset below should be commented out.
|
||||
memset (dtp->u.p.saved_string, 0, SCRATCH_SIZE);
|
||||
dtp->u.p.saved_length = SCRATCH_SIZE;
|
||||
dtp->u.p.saved_used = 0;
|
||||
|
@ -90,15 +90,15 @@ push_char (st_parameter_dt *dtp, char c)
|
|||
if (dtp->u.p.saved_used >= dtp->u.p.saved_length)
|
||||
{
|
||||
dtp->u.p.saved_length = 2 * dtp->u.p.saved_length;
|
||||
new = get_mem (2 * dtp->u.p.saved_length);
|
||||
|
||||
memset (new, 0, 2 * dtp->u.p.saved_length);
|
||||
|
||||
memcpy (new, dtp->u.p.saved_string, dtp->u.p.saved_used);
|
||||
if (dtp->u.p.saved_string != dtp->u.p.scratch)
|
||||
free_mem (dtp->u.p.saved_string);
|
||||
|
||||
new = realloc (dtp->u.p.saved_string, dtp->u.p.saved_length);
|
||||
if (new == NULL)
|
||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
||||
dtp->u.p.saved_string = new;
|
||||
|
||||
// Also this should not be necessary.
|
||||
memset (new + dtp->u.p.saved_used, 0,
|
||||
dtp->u.p.saved_length - dtp->u.p.saved_used);
|
||||
|
||||
}
|
||||
|
||||
dtp->u.p.saved_string[dtp->u.p.saved_used++] = c;
|
||||
|
@ -113,8 +113,7 @@ free_saved (st_parameter_dt *dtp)
|
|||
if (dtp->u.p.saved_string == NULL)
|
||||
return;
|
||||
|
||||
if (dtp->u.p.saved_string != dtp->u.p.scratch)
|
||||
free_mem (dtp->u.p.saved_string);
|
||||
free_mem (dtp->u.p.saved_string);
|
||||
|
||||
dtp->u.p.saved_string = NULL;
|
||||
dtp->u.p.saved_used = 0;
|
||||
|
@ -140,9 +139,10 @@ free_line (st_parameter_dt *dtp)
|
|||
static char
|
||||
next_char (st_parameter_dt *dtp)
|
||||
{
|
||||
size_t length;
|
||||
ssize_t length;
|
||||
gfc_offset record;
|
||||
char c;
|
||||
int cc;
|
||||
|
||||
if (dtp->u.p.last_char != '\0')
|
||||
{
|
||||
|
@ -194,7 +194,7 @@ next_char (st_parameter_dt *dtp)
|
|||
}
|
||||
|
||||
record *= dtp->u.p.current_unit->recl;
|
||||
if (sseek (dtp->u.p.current_unit->s, record) == FAILURE)
|
||||
if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
|
||||
longjmp (*dtp->u.p.eof_jump, 1);
|
||||
|
||||
dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
|
||||
|
@ -204,19 +204,15 @@ next_char (st_parameter_dt *dtp)
|
|||
|
||||
/* Get the next character and handle end-of-record conditions. */
|
||||
|
||||
length = 1;
|
||||
|
||||
if (sread (dtp->u.p.current_unit->s, &c, &length) != 0)
|
||||
{
|
||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
||||
return '\0';
|
||||
}
|
||||
|
||||
if (is_stream_io (dtp) && length == 1)
|
||||
dtp->u.p.current_unit->strm_pos++;
|
||||
|
||||
if (is_internal_unit (dtp))
|
||||
{
|
||||
length = sread (dtp->u.p.current_unit->s, &c, 1);
|
||||
if (length < 0)
|
||||
{
|
||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
||||
return '\0';
|
||||
}
|
||||
|
||||
if (is_array_io (dtp))
|
||||
{
|
||||
/* Check whether we hit EOF. */
|
||||
|
@ -240,13 +236,20 @@ next_char (st_parameter_dt *dtp)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (length == 0)
|
||||
cc = fbuf_getc (dtp->u.p.current_unit);
|
||||
|
||||
if (cc == EOF)
|
||||
{
|
||||
if (dtp->u.p.current_unit->endfile == AT_ENDFILE)
|
||||
longjmp (*dtp->u.p.eof_jump, 1);
|
||||
dtp->u.p.current_unit->endfile = AT_ENDFILE;
|
||||
c = '\n';
|
||||
}
|
||||
else
|
||||
c = (char) cc;
|
||||
if (is_stream_io (dtp) && cc != EOF)
|
||||
dtp->u.p.current_unit->strm_pos++;
|
||||
|
||||
}
|
||||
done:
|
||||
dtp->u.p.at_eol = (c == '\n' || c == '\r');
|
||||
|
@ -1698,7 +1701,7 @@ list_formatted_read_scalar (st_parameter_dt *dtp, volatile bt type, void *p,
|
|||
dtp->u.p.input_complete = 0;
|
||||
dtp->u.p.repeat_count = 1;
|
||||
dtp->u.p.at_eol = 0;
|
||||
|
||||
|
||||
c = eat_spaces (dtp);
|
||||
if (is_separator (c))
|
||||
{
|
||||
|
@ -1853,6 +1856,8 @@ finish_list_read (st_parameter_dt *dtp)
|
|||
|
||||
free_saved (dtp);
|
||||
|
||||
fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
|
||||
|
||||
if (dtp->u.p.at_eol)
|
||||
{
|
||||
dtp->u.p.at_eol = 0;
|
||||
|
@ -2261,8 +2266,8 @@ nml_query (st_parameter_dt *dtp, char c)
|
|||
|
||||
/* Flush the stream to force immediate output. */
|
||||
|
||||
fbuf_flush (dtp->u.p.current_unit, 1);
|
||||
flush (dtp->u.p.current_unit->s);
|
||||
fbuf_flush (dtp->u.p.current_unit, WRITING);
|
||||
sflush (dtp->u.p.current_unit->s);
|
||||
unlock_unit (dtp->u.p.current_unit);
|
||||
}
|
||||
|
||||
|
@ -2903,7 +2908,7 @@ find_nml_name:
|
|||
st_printf ("%s\n", nml_err_msg);
|
||||
if (u != NULL)
|
||||
{
|
||||
flush (u->s);
|
||||
sflush (u->s);
|
||||
unlock_unit (u);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -540,6 +540,8 @@ init_units (void)
|
|||
u->file_len = strlen (stdin_name);
|
||||
u->file = get_mem (u->file_len);
|
||||
memmove (u->file, stdin_name, u->file_len);
|
||||
|
||||
fbuf_init (u, 0);
|
||||
|
||||
__gthread_mutex_unlock (&u->lock);
|
||||
}
|
||||
|
@ -697,15 +699,62 @@ close_units (void)
|
|||
void
|
||||
update_position (gfc_unit *u)
|
||||
{
|
||||
if (file_position (u->s) == 0)
|
||||
if (stell (u->s) == 0)
|
||||
u->flags.position = POSITION_REWIND;
|
||||
else if (file_length (u->s) == file_position (u->s))
|
||||
else if (file_length (u->s) == stell (u->s))
|
||||
u->flags.position = POSITION_APPEND;
|
||||
else
|
||||
u->flags.position = POSITION_ASIS;
|
||||
}
|
||||
|
||||
|
||||
/* High level interface to truncate a file safely, i.e. flush format
|
||||
buffers, check that it's a regular file, and generate error if that
|
||||
occurs. Just like POSIX ftruncate, returns 0 on success, -1 on
|
||||
failure. */
|
||||
|
||||
int
|
||||
unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Make sure format buffer is flushed. */
|
||||
if (u->flags.form == FORM_FORMATTED)
|
||||
{
|
||||
if (u->mode == READING)
|
||||
pos += fbuf_reset (u);
|
||||
else
|
||||
fbuf_flush (u, u->mode);
|
||||
}
|
||||
|
||||
/* Don't try to truncate a special file, just pretend that it
|
||||
succeeds. */
|
||||
if (is_special (u->s) || !is_seekable (u->s))
|
||||
{
|
||||
sflush (u->s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* struncate() should flush the stream buffer if necessary, so don't
|
||||
bother calling sflush() here. */
|
||||
ret = struncate (u->s, pos);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
generate_error (common, LIBERROR_OS, NULL);
|
||||
u->endfile = NO_ENDFILE;
|
||||
u->flags.position = POSITION_ASIS;
|
||||
}
|
||||
else
|
||||
{
|
||||
u->endfile = AT_ENDFILE;
|
||||
u->flags.position = POSITION_APPEND;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* filename_from_unit()-- If the unit_number exists, return a pointer to the
|
||||
name of the associated file, otherwise return the empty string. The caller
|
||||
must free memory allocated for the filename string. */
|
||||
|
@ -746,23 +795,25 @@ finish_last_advance_record (gfc_unit *u)
|
|||
{
|
||||
|
||||
if (u->saved_pos > 0)
|
||||
fbuf_seek (u, u->saved_pos);
|
||||
|
||||
fbuf_flush (u, 1);
|
||||
fbuf_seek (u, u->saved_pos, SEEK_CUR);
|
||||
|
||||
if (!(u->unit_number == options.stdout_unit
|
||||
|| u->unit_number == options.stderr_unit))
|
||||
{
|
||||
size_t len;
|
||||
|
||||
const char crlf[] = "\r\n";
|
||||
#ifdef HAVE_CRLF
|
||||
len = 2;
|
||||
const int len = 2;
|
||||
#else
|
||||
len = 1;
|
||||
const int len = 1;
|
||||
#endif
|
||||
if (swrite (u->s, &crlf[2-len], &len) != 0)
|
||||
char *p = fbuf_alloc (u, len);
|
||||
if (!p)
|
||||
os_error ("Completing record after ADVANCE_NO failed");
|
||||
#ifdef HAVE_CRLF
|
||||
*(p++) = '\r';
|
||||
#endif
|
||||
*p = '\n';
|
||||
}
|
||||
|
||||
fbuf_flush (u, u->mode);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue