mirror of git://gcc.gnu.org/git/gcc.git
Part 1 of PR 25561.
2008-05-15 Janne Blomqvist <jb@gcc.gnu.org> PR libfortran/25561 * Makefile.am: Add fbuf.c to gfor_io_src. * Makefile.in: Regenerate. * io/io.h (read_block): Remove. (struct stream): Remove alloc_r_at function pointer. (salloc_r): Remove. (salloc_r_at): Remove. (salloc_w_at): Remove. (salloc_w): Remove offset argument. (struct fbuf): New struct for format buffer. (struct gfc_unit): Add fbuf. (read_block_form): New prototype. (fbuf_init): Likewise. (fbuf_destroy): Likewise. (fbuf_reset): Likewise. (fbuf_alloc): Likewise. (fbuf_flush): Likewise. (fbuf_seek): Likewise. * io/file_pos.c (formatted_backspace): Change to use sread. (unformatted_backspace): Likewise. (st_backspace): Flush format buffer. (st_rewind): Likewise. * io/list_read.c (next_char): Likewise. (nml_query): Tidying, flush format buffer. * io/open.c (new_unit): Init format buffer. * io/read.c (read_l): Change to use read_block_form. (read_a): Likewise. (read_decimal): Likewise. (read_radix): Likewise. (read_f): Likewise. (read_x): Empty reads also for stream I/O. * io/transfer.c (read_sf): Change to use sread. (read_block): Rename to read_block_form, change prototype, use sread. (read_block_direct): Don't seek stream files. (write_block): Change to use fbuf if external file, don't seek stream files. (write_buf): Don't seek stream files. (formatted_transfer_scalar): Use fbuf for external files. (us_read): Change to use sread. (pre_position): Do nothing for stream I/O. (data_transfer_init): Flush fbuf when switching from write to read, if POS is specified, seek stream file to correct offset. (skip_record): Change to use sread. (min_off): New function. (next_record_r): Change to use sread. (next_record_w): Change to use sset/sseek, flush fbuf. (finalize_transfer): Flush fbuf. * io/unit.c (init_units): Init fbuf for stdout, stderr. (close_unit_1): Destroy fbuf. (finish_last_advance_record): Flush fbuf, no need to seek. * io/unix.c (fd_alloc_r_at): Remove unused where argument. (fd_alloc_w_at): Likewise. (fd_read): Remove third argument to fd_alloc_r_at. (fd_write): Remove third argument to fd_alloc_w_at. (fd_sset): Likewise. (fd_open): Don't set alloc_r_at. (mem_alloc_r_at): Remove unused where argument. (mem_alloc_w_at): Likewise. (mem_read): Don't incorrectly return previous errno, remove unused third argument to alloc function. (mem_write): Likewise. (mem_set): Likewise. (open_internal): Don't set alloc_r_at pointer. * io/fbuf.c: New file. From-SVN: r135373
This commit is contained in:
parent
2819ae08d2
commit
15877a88eb
|
|
@ -47,7 +47,8 @@ io/size_from_kind.c \
|
||||||
io/transfer.c \
|
io/transfer.c \
|
||||||
io/unit.c \
|
io/unit.c \
|
||||||
io/unix.c \
|
io/unix.c \
|
||||||
io/write.c
|
io/write.c \
|
||||||
|
io/fbuf.c
|
||||||
|
|
||||||
gfor_io_headers= \
|
gfor_io_headers= \
|
||||||
io/io.h
|
io/io.h
|
||||||
|
|
|
||||||
|
|
@ -401,8 +401,8 @@ am__libgfortran_la_SOURCES_DIST = runtime/backtrace.c \
|
||||||
fpu-target.h io/close.c io/file_pos.c io/format.c io/inquire.c \
|
fpu-target.h io/close.c io/file_pos.c io/format.c io/inquire.c \
|
||||||
io/intrinsics.c io/list_read.c io/lock.c io/open.c io/read.c \
|
io/intrinsics.c io/list_read.c io/lock.c io/open.c io/read.c \
|
||||||
io/size_from_kind.c io/transfer.c io/unit.c io/unix.c \
|
io/size_from_kind.c io/transfer.c io/unit.c io/unix.c \
|
||||||
io/write.c intrinsics/associated.c intrinsics/abort.c \
|
io/write.c io/fbuf.c intrinsics/associated.c \
|
||||||
intrinsics/access.c intrinsics/args.c \
|
intrinsics/abort.c intrinsics/access.c intrinsics/args.c \
|
||||||
intrinsics/c99_functions.c intrinsics/chdir.c \
|
intrinsics/c99_functions.c intrinsics/chdir.c \
|
||||||
intrinsics/chmod.c intrinsics/clock.c intrinsics/cpu_time.c \
|
intrinsics/chmod.c intrinsics/clock.c intrinsics/cpu_time.c \
|
||||||
intrinsics/cshift0.c intrinsics/ctime.c \
|
intrinsics/cshift0.c intrinsics/ctime.c \
|
||||||
|
|
@ -691,7 +691,7 @@ am__objects_33 = $(am__objects_2) $(am__objects_3) $(am__objects_4) \
|
||||||
$(am__objects_32)
|
$(am__objects_32)
|
||||||
am__objects_34 = close.lo file_pos.lo format.lo inquire.lo \
|
am__objects_34 = close.lo file_pos.lo format.lo inquire.lo \
|
||||||
intrinsics.lo list_read.lo lock.lo open.lo read.lo \
|
intrinsics.lo list_read.lo lock.lo open.lo read.lo \
|
||||||
size_from_kind.lo transfer.lo unit.lo unix.lo write.lo
|
size_from_kind.lo transfer.lo unit.lo unix.lo write.lo fbuf.lo
|
||||||
am__objects_35 = associated.lo abort.lo access.lo args.lo \
|
am__objects_35 = associated.lo abort.lo access.lo args.lo \
|
||||||
c99_functions.lo chdir.lo chmod.lo clock.lo cpu_time.lo \
|
c99_functions.lo chdir.lo chmod.lo clock.lo cpu_time.lo \
|
||||||
cshift0.lo ctime.lo date_and_time.lo dtime.lo env.lo \
|
cshift0.lo ctime.lo date_and_time.lo dtime.lo env.lo \
|
||||||
|
|
@ -946,7 +946,8 @@ io/size_from_kind.c \
|
||||||
io/transfer.c \
|
io/transfer.c \
|
||||||
io/unit.c \
|
io/unit.c \
|
||||||
io/unix.c \
|
io/unix.c \
|
||||||
io/write.c
|
io/write.c \
|
||||||
|
io/fbuf.c
|
||||||
|
|
||||||
gfor_io_headers = \
|
gfor_io_headers = \
|
||||||
io/io.h
|
io/io.h
|
||||||
|
|
@ -1791,6 +1792,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exponent_r16.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exponent_r16.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exponent_r4.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exponent_r4.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exponent_r8.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exponent_r8.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fbuf.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_pos.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_pos.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmain.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmain.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnum.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnum.Plo@am__quote@
|
||||||
|
|
@ -5124,6 +5126,13 @@ write.lo: io/write.c
|
||||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o write.lo `test -f 'io/write.c' || echo '$(srcdir)/'`io/write.c
|
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o write.lo `test -f 'io/write.c' || echo '$(srcdir)/'`io/write.c
|
||||||
|
|
||||||
|
fbuf.lo: io/fbuf.c
|
||||||
|
@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fbuf.lo -MD -MP -MF "$(DEPDIR)/fbuf.Tpo" -c -o fbuf.lo `test -f 'io/fbuf.c' || echo '$(srcdir)/'`io/fbuf.c; \
|
||||||
|
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/fbuf.Tpo" "$(DEPDIR)/fbuf.Plo"; else rm -f "$(DEPDIR)/fbuf.Tpo"; exit 1; fi
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='io/fbuf.c' object='fbuf.lo' libtool=yes @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fbuf.lo `test -f 'io/fbuf.c' || echo '$(srcdir)/'`io/fbuf.c
|
||||||
|
|
||||||
associated.lo: intrinsics/associated.c
|
associated.lo: intrinsics/associated.c
|
||||||
@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT associated.lo -MD -MP -MF "$(DEPDIR)/associated.Tpo" -c -o associated.lo `test -f 'intrinsics/associated.c' || echo '$(srcdir)/'`intrinsics/associated.c; \
|
@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT associated.lo -MD -MP -MF "$(DEPDIR)/associated.Tpo" -c -o associated.lo `test -f 'intrinsics/associated.c' || echo '$(srcdir)/'`intrinsics/associated.c; \
|
||||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/associated.Tpo" "$(DEPDIR)/associated.Plo"; else rm -f "$(DEPDIR)/associated.Tpo"; exit 1; fi
|
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/associated.Tpo" "$(DEPDIR)/associated.Plo"; else rm -f "$(DEPDIR)/associated.Tpo"; exit 1; fi
|
||||||
|
|
|
||||||
|
|
@ -39,14 +39,14 @@ Boston, MA 02110-1301, USA. */
|
||||||
record, and we have to sift backwards to find the newline before
|
record, and we have to sift backwards to find the newline before
|
||||||
that or the start of the file, whichever comes first. */
|
that or the start of the file, whichever comes first. */
|
||||||
|
|
||||||
#define READ_CHUNK 4096
|
static const unsigned int READ_CHUNK = 4096;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
formatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
|
formatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
|
||||||
{
|
{
|
||||||
gfc_offset base;
|
gfc_offset base;
|
||||||
char *p;
|
char p[READ_CHUNK];
|
||||||
int n;
|
size_t n;
|
||||||
|
|
||||||
base = file_position (u->s) - 1;
|
base = file_position (u->s) - 1;
|
||||||
|
|
||||||
|
|
@ -54,9 +54,9 @@ formatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
|
||||||
{
|
{
|
||||||
n = (base < READ_CHUNK) ? base : READ_CHUNK;
|
n = (base < READ_CHUNK) ? base : READ_CHUNK;
|
||||||
base -= n;
|
base -= n;
|
||||||
|
if (sseek (u->s, base) == FAILURE)
|
||||||
p = salloc_r_at (u->s, &n, base);
|
goto io_error;
|
||||||
if (p == NULL)
|
if (sread (u->s, p, &n) != 0)
|
||||||
goto io_error;
|
goto io_error;
|
||||||
|
|
||||||
/* We have moved backwards from the current position, it should
|
/* We have moved backwards from the current position, it should
|
||||||
|
|
@ -66,15 +66,14 @@ formatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
|
||||||
/* There is no memrchr() in the C library, so we have to do it
|
/* There is no memrchr() in the C library, so we have to do it
|
||||||
ourselves. */
|
ourselves. */
|
||||||
|
|
||||||
n--;
|
while (n > 0)
|
||||||
while (n >= 0)
|
|
||||||
{
|
{
|
||||||
|
n--;
|
||||||
if (p[n] == '\n')
|
if (p[n] == '\n')
|
||||||
{
|
{
|
||||||
base += n + 1;
|
base += n + 1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
n--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -104,9 +103,9 @@ unformatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
|
||||||
gfc_offset m, new;
|
gfc_offset m, new;
|
||||||
GFC_INTEGER_4 m4;
|
GFC_INTEGER_4 m4;
|
||||||
GFC_INTEGER_8 m8;
|
GFC_INTEGER_8 m8;
|
||||||
int length, length_read;
|
size_t length;
|
||||||
int continued;
|
int continued;
|
||||||
char *p;
|
char p[sizeof (GFC_INTEGER_8)];
|
||||||
|
|
||||||
if (compile_options.record_marker == 0)
|
if (compile_options.record_marker == 0)
|
||||||
length = sizeof (GFC_INTEGER_4);
|
length = sizeof (GFC_INTEGER_4);
|
||||||
|
|
@ -115,12 +114,10 @@ unformatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
length_read = length;
|
if (sseek (u->s, file_position (u->s) - length) == FAILURE)
|
||||||
|
goto io_error;
|
||||||
p = salloc_r_at (u->s, &length_read,
|
if (sread (u->s, p, &length) != 0)
|
||||||
file_position (u->s) - length);
|
goto io_error;
|
||||||
if (p == NULL || length_read != length)
|
|
||||||
goto io_error;
|
|
||||||
|
|
||||||
/* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */
|
/* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */
|
||||||
if (u->flags.convert == GFC_CONVERT_NATIVE)
|
if (u->flags.convert == GFC_CONVERT_NATIVE)
|
||||||
|
|
@ -216,6 +213,9 @@ st_backspace (st_parameter_filepos *fpp)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure format buffer is flushed. */
|
||||||
|
fbuf_flush (u, 1);
|
||||||
|
|
||||||
/* Check for special cases involving the ENDFILE record first. */
|
/* Check for special cases involving the ENDFILE record first. */
|
||||||
|
|
||||||
if (u->endfile == AFTER_ENDFILE)
|
if (u->endfile == AFTER_ENDFILE)
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,7 @@ struct st_parameter_dt;
|
||||||
|
|
||||||
typedef struct stream
|
typedef struct stream
|
||||||
{
|
{
|
||||||
char *(*alloc_w_at) (struct stream *, int *, gfc_offset);
|
char *(*alloc_w_at) (struct stream *, int *);
|
||||||
char *(*alloc_r_at) (struct stream *, int *, gfc_offset);
|
|
||||||
try (*sfree) (struct stream *);
|
try (*sfree) (struct stream *);
|
||||||
try (*close) (struct stream *);
|
try (*close) (struct stream *);
|
||||||
try (*seek) (struct stream *, gfc_offset);
|
try (*seek) (struct stream *, gfc_offset);
|
||||||
|
|
@ -70,11 +69,7 @@ io_mode;
|
||||||
#define sfree(s) ((s)->sfree)(s)
|
#define sfree(s) ((s)->sfree)(s)
|
||||||
#define sclose(s) ((s)->close)(s)
|
#define sclose(s) ((s)->close)(s)
|
||||||
|
|
||||||
#define salloc_r(s, len) ((s)->alloc_r_at)(s, len, -1)
|
#define salloc_w(s, len) ((s)->alloc_w_at)(s, len)
|
||||||
#define salloc_w(s, len) ((s)->alloc_w_at)(s, len, -1)
|
|
||||||
|
|
||||||
#define salloc_r_at(s, len, where) ((s)->alloc_r_at)(s, len, where)
|
|
||||||
#define salloc_w_at(s, len, where) ((s)->alloc_w_at)(s, len, where)
|
|
||||||
|
|
||||||
#define sseek(s, pos) ((s)->seek)(s, pos)
|
#define sseek(s, pos) ((s)->seek)(s, pos)
|
||||||
#define struncate(s) ((s)->trunc)(s)
|
#define struncate(s) ((s)->trunc)(s)
|
||||||
|
|
@ -528,6 +523,25 @@ typedef struct
|
||||||
unit_flags;
|
unit_flags;
|
||||||
|
|
||||||
|
|
||||||
|
/* Formatting buffer. This is a temporary scratch buffer. Currently used only
|
||||||
|
by formatted writes. After every
|
||||||
|
formatted write statement, this buffer is flushed. This buffer is needed since
|
||||||
|
not all devices are seekable, and T or TL edit descriptors require
|
||||||
|
moving backwards in the record. However, advance='no' complicates the
|
||||||
|
situation, so the buffer must only be partially flushed from the end of the
|
||||||
|
last flush until the current position in the record. */
|
||||||
|
|
||||||
|
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. */
|
||||||
|
char *ptr; /* Current position in buffer. */
|
||||||
|
}
|
||||||
|
fbuf;
|
||||||
|
|
||||||
|
|
||||||
typedef struct gfc_unit
|
typedef struct gfc_unit
|
||||||
{
|
{
|
||||||
int unit_number;
|
int unit_number;
|
||||||
|
|
@ -578,6 +592,9 @@ typedef struct gfc_unit
|
||||||
|
|
||||||
int file_len;
|
int file_len;
|
||||||
char *file;
|
char *file;
|
||||||
|
|
||||||
|
/* Formatting buffer. */
|
||||||
|
struct fbuf *fbuf;
|
||||||
}
|
}
|
||||||
gfc_unit;
|
gfc_unit;
|
||||||
|
|
||||||
|
|
@ -812,8 +829,8 @@ internal_proto(free_format_data);
|
||||||
extern const char *type_name (bt);
|
extern const char *type_name (bt);
|
||||||
internal_proto(type_name);
|
internal_proto(type_name);
|
||||||
|
|
||||||
extern void *read_block (st_parameter_dt *, int *);
|
extern try read_block_form (st_parameter_dt *, void *, size_t *);
|
||||||
internal_proto(read_block);
|
internal_proto(read_block_form);
|
||||||
|
|
||||||
extern char *read_sf (st_parameter_dt *, int *, int);
|
extern char *read_sf (st_parameter_dt *, int *, int);
|
||||||
internal_proto(read_sf);
|
internal_proto(read_sf);
|
||||||
|
|
@ -931,6 +948,25 @@ internal_proto(size_from_real_kind);
|
||||||
extern size_t size_from_complex_kind (int);
|
extern size_t size_from_complex_kind (int);
|
||||||
internal_proto(size_from_complex_kind);
|
internal_proto(size_from_complex_kind);
|
||||||
|
|
||||||
|
/* fbuf.c */
|
||||||
|
extern void fbuf_init (gfc_unit *, size_t);
|
||||||
|
internal_proto(fbuf_init);
|
||||||
|
|
||||||
|
extern void fbuf_destroy (gfc_unit *);
|
||||||
|
internal_proto(fbuf_destroy);
|
||||||
|
|
||||||
|
extern void fbuf_reset (gfc_unit *);
|
||||||
|
internal_proto(fbuf_reset);
|
||||||
|
|
||||||
|
extern char * fbuf_alloc (gfc_unit *, size_t);
|
||||||
|
internal_proto(fbuf_alloc);
|
||||||
|
|
||||||
|
extern int fbuf_flush (gfc_unit *, int);
|
||||||
|
internal_proto(fbuf_flush);
|
||||||
|
|
||||||
|
extern int fbuf_seek (gfc_unit *, gfc_offset);
|
||||||
|
internal_proto(fbuf_seek);
|
||||||
|
|
||||||
/* lock.c */
|
/* lock.c */
|
||||||
extern void free_ionml (st_parameter_dt *);
|
extern void free_ionml (st_parameter_dt *);
|
||||||
internal_proto(free_ionml);
|
internal_proto(free_ionml);
|
||||||
|
|
|
||||||
|
|
@ -140,9 +140,9 @@ free_line (st_parameter_dt *dtp)
|
||||||
static char
|
static char
|
||||||
next_char (st_parameter_dt *dtp)
|
next_char (st_parameter_dt *dtp)
|
||||||
{
|
{
|
||||||
int length;
|
size_t length;
|
||||||
gfc_offset record;
|
gfc_offset record;
|
||||||
char c, *p;
|
char c;
|
||||||
|
|
||||||
if (dtp->u.p.last_char != '\0')
|
if (dtp->u.p.last_char != '\0')
|
||||||
{
|
{
|
||||||
|
|
@ -206,43 +206,40 @@ next_char (st_parameter_dt *dtp)
|
||||||
|
|
||||||
length = 1;
|
length = 1;
|
||||||
|
|
||||||
p = salloc_r (dtp->u.p.current_unit->s, &length);
|
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))
|
if (is_stream_io (dtp) && length == 1)
|
||||||
dtp->u.p.current_unit->strm_pos++;
|
dtp->u.p.current_unit->strm_pos++;
|
||||||
|
|
||||||
if (is_internal_unit (dtp))
|
if (is_internal_unit (dtp))
|
||||||
{
|
{
|
||||||
if (is_array_io (dtp))
|
if (is_array_io (dtp))
|
||||||
{
|
{
|
||||||
/* End of record is handled in the next pass through, above. The
|
/* Check whether we hit EOF. */
|
||||||
check for NULL here is cautionary. */
|
if (length == 0)
|
||||||
if (p == NULL)
|
|
||||||
{
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
|
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
|
||||||
return '\0';
|
return '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
dtp->u.p.current_unit->bytes_left--;
|
dtp->u.p.current_unit->bytes_left--;
|
||||||
c = *p;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (p == NULL)
|
if (dtp->u.p.at_eof)
|
||||||
longjmp (*dtp->u.p.eof_jump, 1);
|
longjmp (*dtp->u.p.eof_jump, 1);
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
c = '\n';
|
{
|
||||||
else
|
c = '\n';
|
||||||
c = *p;
|
dtp->u.p.at_eof = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (p == NULL)
|
|
||||||
{
|
|
||||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
|
||||||
return '\0';
|
|
||||||
}
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
{
|
{
|
||||||
if (dtp->u.p.advance_status == ADVANCE_NO)
|
if (dtp->u.p.advance_status == ADVANCE_NO)
|
||||||
|
|
@ -255,8 +252,6 @@ next_char (st_parameter_dt *dtp)
|
||||||
else
|
else
|
||||||
longjmp (*dtp->u.p.eof_jump, 1);
|
longjmp (*dtp->u.p.eof_jump, 1);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
c = *p;
|
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
dtp->u.p.at_eol = (c == '\n' || c == '\r');
|
dtp->u.p.at_eol = (c == '\n' || c == '\r');
|
||||||
|
|
@ -2226,6 +2221,15 @@ nml_query (st_parameter_dt *dtp, char c)
|
||||||
namelist_info * nl;
|
namelist_info * nl;
|
||||||
index_type len;
|
index_type len;
|
||||||
char * p;
|
char * p;
|
||||||
|
#ifdef HAVE_CRLF
|
||||||
|
static const index_type endlen = 3;
|
||||||
|
static const char endl[] = "\r\n";
|
||||||
|
static const char nmlend[] = "&end\r\n";
|
||||||
|
#else
|
||||||
|
static const index_type endlen = 2;
|
||||||
|
static const char endl[] = "\n";
|
||||||
|
static const char nmlend[] = "&end\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
if (dtp->u.p.current_unit->unit_number != options.stdin_unit)
|
if (dtp->u.p.current_unit->unit_number != options.stdin_unit)
|
||||||
return;
|
return;
|
||||||
|
|
@ -2252,59 +2256,35 @@ nml_query (st_parameter_dt *dtp, char c)
|
||||||
/* "&namelist_name\n" */
|
/* "&namelist_name\n" */
|
||||||
|
|
||||||
len = dtp->namelist_name_len;
|
len = dtp->namelist_name_len;
|
||||||
#ifdef HAVE_CRLF
|
p = write_block (dtp, len + endlen);
|
||||||
p = write_block (dtp, len + 3);
|
if (!p)
|
||||||
#else
|
goto query_return;
|
||||||
p = write_block (dtp, len + 2);
|
|
||||||
#endif
|
|
||||||
if (!p)
|
|
||||||
goto query_return;
|
|
||||||
memcpy (p, "&", 1);
|
memcpy (p, "&", 1);
|
||||||
memcpy ((char*)(p + 1), dtp->namelist_name, len);
|
memcpy ((char*)(p + 1), dtp->namelist_name, len);
|
||||||
#ifdef HAVE_CRLF
|
memcpy ((char*)(p + len + 1), &endl, endlen - 1);
|
||||||
memcpy ((char*)(p + len + 1), "\r\n", 2);
|
|
||||||
#else
|
|
||||||
memcpy ((char*)(p + len + 1), "\n", 1);
|
|
||||||
#endif
|
|
||||||
for (nl = dtp->u.p.ionml; nl; nl = nl->next)
|
for (nl = dtp->u.p.ionml; nl; nl = nl->next)
|
||||||
{
|
{
|
||||||
/* " var_name\n" */
|
/* " var_name\n" */
|
||||||
|
|
||||||
len = strlen (nl->var_name);
|
len = strlen (nl->var_name);
|
||||||
#ifdef HAVE_CRLF
|
p = write_block (dtp, len + endlen);
|
||||||
p = write_block (dtp, len + 3);
|
|
||||||
#else
|
|
||||||
p = write_block (dtp, len + 2);
|
|
||||||
#endif
|
|
||||||
if (!p)
|
if (!p)
|
||||||
goto query_return;
|
goto query_return;
|
||||||
memcpy (p, " ", 1);
|
memcpy (p, " ", 1);
|
||||||
memcpy ((char*)(p + 1), nl->var_name, len);
|
memcpy ((char*)(p + 1), nl->var_name, len);
|
||||||
#ifdef HAVE_CRLF
|
memcpy ((char*)(p + len + 1), &endl, endlen - 1);
|
||||||
memcpy ((char*)(p + len + 1), "\r\n", 2);
|
|
||||||
#else
|
|
||||||
memcpy ((char*)(p + len + 1), "\n", 1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "&end\n" */
|
/* "&end\n" */
|
||||||
|
|
||||||
#ifdef HAVE_CRLF
|
p = write_block (dtp, endlen + 3);
|
||||||
p = write_block (dtp, 6);
|
|
||||||
#else
|
|
||||||
p = write_block (dtp, 5);
|
|
||||||
#endif
|
|
||||||
if (!p)
|
|
||||||
goto query_return;
|
goto query_return;
|
||||||
#ifdef HAVE_CRLF
|
memcpy (p, &nmlend, endlen + 3);
|
||||||
memcpy (p, "&end\r\n", 6);
|
|
||||||
#else
|
|
||||||
memcpy (p, "&end\n", 5);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush the stream to force immediate output. */
|
/* Flush the stream to force immediate output. */
|
||||||
|
|
||||||
|
fbuf_flush (dtp->u.p.current_unit, 1);
|
||||||
flush (dtp->u.p.current_unit->s);
|
flush (dtp->u.p.current_unit->s);
|
||||||
unlock_unit (dtp->u.p.current_unit);
|
unlock_unit (dtp->u.p.current_unit);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -626,6 +626,13 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
|
||||||
|
|
||||||
if (flags->status == STATUS_SCRATCH && opp->file != NULL)
|
if (flags->status == STATUS_SCRATCH && opp->file != NULL)
|
||||||
free_mem (opp->file);
|
free_mem (opp->file);
|
||||||
|
|
||||||
|
if (flags->form == FORM_FORMATTED && (flags->action != ACTION_READ))
|
||||||
|
fbuf_init (u, 0);
|
||||||
|
else
|
||||||
|
u->fbuf = NULL;
|
||||||
|
|
||||||
|
|
||||||
return u;
|
return u;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ Boston, MA 02110-1301, USA. */
|
||||||
|
|
||||||
/* read.c -- Deal with formatted reads */
|
/* read.c -- Deal with formatted reads */
|
||||||
|
|
||||||
|
|
||||||
/* set_integer()-- All of the integer assignments come here to
|
/* set_integer()-- All of the integer assignments come here to
|
||||||
* actually place the value into memory. */
|
* actually place the value into memory. */
|
||||||
|
|
||||||
|
|
@ -192,11 +193,13 @@ void
|
||||||
read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
int w;
|
size_t w;
|
||||||
|
|
||||||
w = f->u.w;
|
w = f->u.w;
|
||||||
p = read_block (dtp, &w);
|
|
||||||
if (p == NULL)
|
p = gfc_alloca (w);
|
||||||
|
|
||||||
|
if (read_block_form (dtp, p, &w) == FAILURE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (*p == ' ')
|
while (*p == ' ')
|
||||||
|
|
@ -238,24 +241,29 @@ read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
||||||
void
|
void
|
||||||
read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length)
|
read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length)
|
||||||
{
|
{
|
||||||
char *source;
|
char *s;
|
||||||
int w, m, n;
|
int m, n, wi, status;
|
||||||
|
size_t w;
|
||||||
|
|
||||||
w = f->u.w;
|
wi = f->u.w;
|
||||||
if (w == -1) /* '(A)' edit descriptor */
|
if (wi == -1) /* '(A)' edit descriptor */
|
||||||
w = length;
|
wi = length;
|
||||||
|
|
||||||
|
w = wi;
|
||||||
|
|
||||||
|
s = gfc_alloca (w);
|
||||||
|
|
||||||
dtp->u.p.sf_read_comma = 0;
|
dtp->u.p.sf_read_comma = 0;
|
||||||
source = read_block (dtp, &w);
|
status = read_block_form (dtp, s, &w);
|
||||||
dtp->u.p.sf_read_comma =
|
dtp->u.p.sf_read_comma =
|
||||||
dtp->u.p.decimal_status == DECIMAL_COMMA ? 0 : 1;
|
dtp->u.p.decimal_status == DECIMAL_COMMA ? 0 : 1;
|
||||||
if (source == NULL)
|
if (status == FAILURE)
|
||||||
return;
|
return;
|
||||||
if (w > length)
|
if (w > (size_t) length)
|
||||||
source += (w - length);
|
s += (w - length);
|
||||||
|
|
||||||
m = (w > length) ? length : w;
|
m = ((int) w > length) ? length : (int) w;
|
||||||
memcpy (p, source, m);
|
memcpy (p, s, m);
|
||||||
|
|
||||||
n = length - w;
|
n = length - w;
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
|
|
@ -323,14 +331,19 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
||||||
{
|
{
|
||||||
GFC_UINTEGER_LARGEST value, maxv, maxv_10;
|
GFC_UINTEGER_LARGEST value, maxv, maxv_10;
|
||||||
GFC_INTEGER_LARGEST v;
|
GFC_INTEGER_LARGEST v;
|
||||||
int w, negative;
|
int w, negative;
|
||||||
|
size_t wu;
|
||||||
char c, *p;
|
char c, *p;
|
||||||
|
|
||||||
w = f->u.w;
|
wu = f->u.w;
|
||||||
p = read_block (dtp, &w);
|
|
||||||
if (p == NULL)
|
p = gfc_alloca (wu);
|
||||||
|
|
||||||
|
if (read_block_form (dtp, p, &wu) == FAILURE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
w = wu;
|
||||||
|
|
||||||
p = eat_leading_spaces (&w, p);
|
p = eat_leading_spaces (&w, p);
|
||||||
if (w == 0)
|
if (w == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -406,7 +419,7 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
||||||
generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
|
generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
|
||||||
"Value overflowed during integer read");
|
"Value overflowed during integer read");
|
||||||
next_record (dtp, 1);
|
next_record (dtp, 1);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -423,12 +436,17 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
|
||||||
GFC_INTEGER_LARGEST v;
|
GFC_INTEGER_LARGEST v;
|
||||||
int w, negative;
|
int w, negative;
|
||||||
char c, *p;
|
char c, *p;
|
||||||
|
size_t wu;
|
||||||
|
|
||||||
w = f->u.w;
|
wu = f->u.w;
|
||||||
p = read_block (dtp, &w);
|
|
||||||
if (p == NULL)
|
p = gfc_alloca (wu);
|
||||||
|
|
||||||
|
if (read_block_form (dtp, p, &wu) == FAILURE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
w = wu;
|
||||||
|
|
||||||
p = eat_leading_spaces (&w, p);
|
p = eat_leading_spaces (&w, p);
|
||||||
if (w == 0)
|
if (w == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -552,7 +570,7 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
|
||||||
generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
|
generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
|
||||||
"Value overflowed during integer read");
|
"Value overflowed during integer read");
|
||||||
next_record (dtp, 1);
|
next_record (dtp, 1);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -565,6 +583,7 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
|
||||||
void
|
void
|
||||||
read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
||||||
{
|
{
|
||||||
|
size_t wu;
|
||||||
int w, seen_dp, exponent;
|
int w, seen_dp, exponent;
|
||||||
int exponent_sign, val_sign;
|
int exponent_sign, val_sign;
|
||||||
int ndigits;
|
int ndigits;
|
||||||
|
|
@ -576,11 +595,15 @@ read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
||||||
|
|
||||||
val_sign = 1;
|
val_sign = 1;
|
||||||
seen_dp = 0;
|
seen_dp = 0;
|
||||||
w = f->u.w;
|
wu = f->u.w;
|
||||||
p = read_block (dtp, &w);
|
|
||||||
if (p == NULL)
|
p = gfc_alloca (wu);
|
||||||
|
|
||||||
|
if (read_block_form (dtp, p, &wu) == FAILURE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
w = wu;
|
||||||
|
|
||||||
p = eat_leading_spaces (&w, p);
|
p = eat_leading_spaces (&w, p);
|
||||||
if (w == 0)
|
if (w == 0)
|
||||||
goto zero;
|
goto zero;
|
||||||
|
|
@ -842,7 +865,6 @@ read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
||||||
if (buffer != scratch)
|
if (buffer != scratch)
|
||||||
free_mem (buffer);
|
free_mem (buffer);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -850,19 +872,16 @@ read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
|
||||||
* and never look at it. */
|
* and never look at it. */
|
||||||
|
|
||||||
void
|
void
|
||||||
read_x (st_parameter_dt *dtp, int n)
|
read_x (st_parameter_dt * dtp, int n)
|
||||||
{
|
{
|
||||||
if (!is_stream_io (dtp))
|
if ((dtp->u.p.pad_status == PAD_NO || is_internal_unit (dtp))
|
||||||
{
|
&& dtp->u.p.current_unit->bytes_left < n)
|
||||||
if ((dtp->u.p.pad_status == PAD_NO || is_internal_unit (dtp))
|
n = dtp->u.p.current_unit->bytes_left;
|
||||||
&& dtp->u.p.current_unit->bytes_left < n)
|
|
||||||
n = dtp->u.p.current_unit->bytes_left;
|
|
||||||
|
|
||||||
dtp->u.p.sf_read_comma = 0;
|
dtp->u.p.sf_read_comma = 0;
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
read_sf (dtp, &n, 1);
|
read_sf (dtp, &n, 1);
|
||||||
dtp->u.p.sf_read_comma = 1;
|
dtp->u.p.sf_read_comma = 1;
|
||||||
}
|
dtp->u.p.current_unit->strm_pos += (gfc_offset) n;
|
||||||
else
|
|
||||||
dtp->u.p.current_unit->strm_pos += (gfc_offset) n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ Boston, MA 02110-1301, USA. */
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
/* Calling conventions: Data transfer statements are unlike other
|
/* Calling conventions: Data transfer statements are unlike other
|
||||||
|
|
@ -180,9 +181,10 @@ current_mode (st_parameter_dt *dtp)
|
||||||
char *
|
char *
|
||||||
read_sf (st_parameter_dt *dtp, int *length, int no_error)
|
read_sf (st_parameter_dt *dtp, int *length, int no_error)
|
||||||
{
|
{
|
||||||
char *base, *p, *q;
|
char *base, *p, q;
|
||||||
int n, readlen, crlf;
|
int n, crlf;
|
||||||
gfc_offset pos;
|
gfc_offset pos;
|
||||||
|
size_t readlen;
|
||||||
|
|
||||||
if (*length > SCRATCH_SIZE)
|
if (*length > SCRATCH_SIZE)
|
||||||
dtp->u.p.line_buffer = get_mem (*length);
|
dtp->u.p.line_buffer = get_mem (*length);
|
||||||
|
|
@ -199,15 +201,12 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
|
||||||
if (is_internal_unit (dtp))
|
if (is_internal_unit (dtp))
|
||||||
{
|
{
|
||||||
readlen = *length;
|
readlen = *length;
|
||||||
q = salloc_r (dtp->u.p.current_unit->s, &readlen);
|
if (sread (dtp->u.p.current_unit->s, p, &readlen) != 0 || readlen < (size_t) *length)
|
||||||
if (readlen < *length)
|
|
||||||
{
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_END, NULL);
|
generate_error (&dtp->common, LIBERROR_END, NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q != NULL)
|
|
||||||
memcpy (p, q, readlen);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,9 +215,11 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
q = salloc_r (dtp->u.p.current_unit->s, &readlen);
|
if (sread (dtp->u.p.current_unit->s, &q, &readlen) != 0)
|
||||||
if (q == NULL)
|
{
|
||||||
break;
|
generate_error (&dtp->common, LIBERROR_END, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we have a line without a terminating \n, drop through to
|
/* If we have a line without a terminating \n, drop through to
|
||||||
EOR below. */
|
EOR below. */
|
||||||
|
|
@ -230,7 +231,7 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readlen < 1 || *q == '\n' || *q == '\r')
|
if (readlen < 1 || q == '\n' || q == '\r')
|
||||||
{
|
{
|
||||||
/* Unexpected end of line. */
|
/* Unexpected end of line. */
|
||||||
|
|
||||||
|
|
@ -241,12 +242,16 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
|
||||||
|
|
||||||
crlf = 0;
|
crlf = 0;
|
||||||
/* If we encounter a CR, it might be a CRLF. */
|
/* If we encounter a CR, it might be a CRLF. */
|
||||||
if (*q == '\r') /* Probably a CRLF */
|
if (q == '\r') /* Probably a CRLF */
|
||||||
{
|
{
|
||||||
readlen = 1;
|
readlen = 1;
|
||||||
pos = stream_offset (dtp->u.p.current_unit->s);
|
pos = stream_offset (dtp->u.p.current_unit->s);
|
||||||
q = salloc_r (dtp->u.p.current_unit->s, &readlen);
|
if (sread (dtp->u.p.current_unit->s, &q, &readlen) != 0)
|
||||||
if (*q != '\n' && readlen == 1) /* Not a CRLF after all. */
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_END, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (q != '\n' && readlen == 1) /* Not a CRLF after all. */
|
||||||
sseek (dtp->u.p.current_unit->s, pos);
|
sseek (dtp->u.p.current_unit->s, pos);
|
||||||
else
|
else
|
||||||
crlf = 1;
|
crlf = 1;
|
||||||
|
|
@ -270,7 +275,7 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
|
||||||
/* Short circuit the read if a comma is found during numeric input.
|
/* Short circuit the read if a comma is found during numeric input.
|
||||||
The flag is set to zero during character reads so that commas in
|
The flag is set to zero during character reads so that commas in
|
||||||
strings are not ignored */
|
strings are not ignored */
|
||||||
if (*q == ',')
|
if (q == ',')
|
||||||
if (dtp->u.p.sf_read_comma == 1)
|
if (dtp->u.p.sf_read_comma == 1)
|
||||||
{
|
{
|
||||||
notify_std (&dtp->common, GFC_STD_GNU,
|
notify_std (&dtp->common, GFC_STD_GNU,
|
||||||
|
|
@ -280,7 +285,7 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
*p++ = *q;
|
*p++ = q;
|
||||||
dtp->u.p.sf_seen_eor = 0;
|
dtp->u.p.sf_seen_eor = 0;
|
||||||
}
|
}
|
||||||
while (n < *length);
|
while (n < *length);
|
||||||
|
|
@ -296,35 +301,25 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
|
||||||
|
|
||||||
|
|
||||||
/* Function for reading the next couple of bytes from the current
|
/* Function for reading the next couple of bytes from the current
|
||||||
file, advancing the current position. We return a pointer to a
|
file, advancing the current position. We return FAILURE on end of record or
|
||||||
buffer containing the bytes. We return NULL on end of record or
|
end of file. This function is only for formatted I/O, unformatted uses
|
||||||
end of file.
|
read_block_direct.
|
||||||
|
|
||||||
If the read is short, then it is because the current record does not
|
If the read is short, then it is because the current record does not
|
||||||
have enough data to satisfy the read request and the file was
|
have enough data to satisfy the read request and the file was
|
||||||
opened with PAD=YES. The caller must assume tailing spaces for
|
opened with PAD=YES. The caller must assume tailing spaces for
|
||||||
short reads. */
|
short reads. */
|
||||||
|
|
||||||
void *
|
try
|
||||||
read_block (st_parameter_dt *dtp, int *length)
|
read_block_form (st_parameter_dt *dtp, void *buf, size_t *nbytes)
|
||||||
{
|
{
|
||||||
char *source;
|
char *source;
|
||||||
int nread;
|
size_t nread;
|
||||||
|
int nb;
|
||||||
|
|
||||||
if (is_stream_io (dtp))
|
if (!is_stream_io (dtp))
|
||||||
{
|
{
|
||||||
if (dtp->u.p.current_unit->strm_pos - 1
|
if (dtp->u.p.current_unit->bytes_left < (gfc_offset) *nbytes)
|
||||||
!= file_position (dtp->u.p.current_unit->s)
|
|
||||||
&& sseek (dtp->u.p.current_unit->s,
|
|
||||||
dtp->u.p.current_unit->strm_pos - 1) == FAILURE)
|
|
||||||
{
|
|
||||||
generate_error (&dtp->common, LIBERROR_END, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dtp->u.p.current_unit->bytes_left < (gfc_offset) *length)
|
|
||||||
{
|
{
|
||||||
/* For preconnected units with default record length, set bytes left
|
/* For preconnected units with default record length, set bytes left
|
||||||
to unit record length and proceed, otherwise error. */
|
to unit record length and proceed, otherwise error. */
|
||||||
|
|
@ -337,7 +332,7 @@ read_block (st_parameter_dt *dtp, int *length)
|
||||||
{
|
{
|
||||||
/* Not enough data left. */
|
/* Not enough data left. */
|
||||||
generate_error (&dtp->common, LIBERROR_EOR, NULL);
|
generate_error (&dtp->common, LIBERROR_EOR, NULL);
|
||||||
return NULL;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -345,10 +340,10 @@ read_block (st_parameter_dt *dtp, int *length)
|
||||||
{
|
{
|
||||||
dtp->u.p.current_unit->endfile = AT_ENDFILE;
|
dtp->u.p.current_unit->endfile = AT_ENDFILE;
|
||||||
generate_error (&dtp->common, LIBERROR_END, NULL);
|
generate_error (&dtp->common, LIBERROR_END, NULL);
|
||||||
return NULL;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*length = dtp->u.p.current_unit->bytes_left;
|
*nbytes = dtp->u.p.current_unit->bytes_left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -356,23 +351,32 @@ read_block (st_parameter_dt *dtp, int *length)
|
||||||
(dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL ||
|
(dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL ||
|
||||||
dtp->u.p.current_unit->flags.access == ACCESS_STREAM))
|
dtp->u.p.current_unit->flags.access == ACCESS_STREAM))
|
||||||
{
|
{
|
||||||
source = read_sf (dtp, length, 0);
|
nb = *nbytes;
|
||||||
|
source = read_sf (dtp, &nb, 0);
|
||||||
|
*nbytes = nb;
|
||||||
dtp->u.p.current_unit->strm_pos +=
|
dtp->u.p.current_unit->strm_pos +=
|
||||||
(gfc_offset) (*length + dtp->u.p.sf_seen_eor);
|
(gfc_offset) (*nbytes + dtp->u.p.sf_seen_eor);
|
||||||
return source;
|
if (source == NULL)
|
||||||
|
return FAILURE;
|
||||||
|
memcpy (buf, source, *nbytes);
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
dtp->u.p.current_unit->bytes_left -= (gfc_offset) *length;
|
dtp->u.p.current_unit->bytes_left -= (gfc_offset) *nbytes;
|
||||||
|
|
||||||
nread = *length;
|
nread = *nbytes;
|
||||||
source = salloc_r (dtp->u.p.current_unit->s, &nread);
|
if (sread (dtp->u.p.current_unit->s, buf, &nread) != 0)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
|
if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
|
||||||
dtp->u.p.size_used += (gfc_offset) nread;
|
dtp->u.p.size_used += (gfc_offset) nread;
|
||||||
|
|
||||||
if (nread != *length)
|
if (nread != *nbytes)
|
||||||
{ /* Short read, this shouldn't happen. */
|
{ /* Short read, this shouldn't happen. */
|
||||||
if (dtp->u.p.pad_status == PAD_YES)
|
if (dtp->u.p.pad_status == PAD_YES)
|
||||||
*length = nread;
|
*nbytes = nread;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_EOR, NULL);
|
generate_error (&dtp->common, LIBERROR_EOR, NULL);
|
||||||
|
|
@ -382,7 +386,7 @@ read_block (st_parameter_dt *dtp, int *length)
|
||||||
|
|
||||||
dtp->u.p.current_unit->strm_pos += (gfc_offset) nread;
|
dtp->u.p.current_unit->strm_pos += (gfc_offset) nread;
|
||||||
|
|
||||||
return source;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -400,15 +404,6 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
|
||||||
|
|
||||||
if (is_stream_io (dtp))
|
if (is_stream_io (dtp))
|
||||||
{
|
{
|
||||||
if (dtp->u.p.current_unit->strm_pos - 1
|
|
||||||
!= file_position (dtp->u.p.current_unit->s)
|
|
||||||
&& sseek (dtp->u.p.current_unit->s,
|
|
||||||
dtp->u.p.current_unit->strm_pos - 1) == FAILURE)
|
|
||||||
{
|
|
||||||
generate_error (&dtp->common, LIBERROR_END, NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
to_read_record = *nbytes;
|
to_read_record = *nbytes;
|
||||||
have_read_record = to_read_record;
|
have_read_record = to_read_record;
|
||||||
if (sread (dtp->u.p.current_unit->s, buf, &have_read_record) != 0)
|
if (sread (dtp->u.p.current_unit->s, buf, &have_read_record) != 0)
|
||||||
|
|
@ -576,18 +571,7 @@ write_block (st_parameter_dt *dtp, int length)
|
||||||
{
|
{
|
||||||
char *dest;
|
char *dest;
|
||||||
|
|
||||||
if (is_stream_io (dtp))
|
if (!is_stream_io (dtp))
|
||||||
{
|
|
||||||
if (dtp->u.p.current_unit->strm_pos - 1
|
|
||||||
!= file_position (dtp->u.p.current_unit->s)
|
|
||||||
&& sseek (dtp->u.p.current_unit->s,
|
|
||||||
dtp->u.p.current_unit->strm_pos - 1) == FAILURE)
|
|
||||||
{
|
|
||||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (dtp->u.p.current_unit->bytes_left < (gfc_offset) length)
|
if (dtp->u.p.current_unit->bytes_left < (gfc_offset) length)
|
||||||
{
|
{
|
||||||
|
|
@ -607,17 +591,29 @@ write_block (st_parameter_dt *dtp, int length)
|
||||||
dtp->u.p.current_unit->bytes_left -= (gfc_offset) length;
|
dtp->u.p.current_unit->bytes_left -= (gfc_offset) length;
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = salloc_w (dtp->u.p.current_unit->s, &length);
|
if (is_internal_unit (dtp))
|
||||||
|
|
||||||
if (dest == NULL)
|
|
||||||
{
|
{
|
||||||
|
dest = salloc_w (dtp->u.p.current_unit->s, &length);
|
||||||
|
|
||||||
|
if (dest == NULL)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_END, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dtp->u.p.current_unit->endfile == AT_ENDFILE)
|
||||||
generate_error (&dtp->common, LIBERROR_END, NULL);
|
generate_error (&dtp->common, LIBERROR_END, NULL);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (is_internal_unit (dtp) && dtp->u.p.current_unit->endfile == AT_ENDFILE)
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_END, NULL);
|
dest = fbuf_alloc (dtp->u.p.current_unit, length);
|
||||||
|
if (dest == NULL)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
|
if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
|
||||||
dtp->u.p.size_used += (gfc_offset) length;
|
dtp->u.p.size_used += (gfc_offset) length;
|
||||||
|
|
||||||
|
|
@ -642,15 +638,6 @@ write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes)
|
||||||
|
|
||||||
if (is_stream_io (dtp))
|
if (is_stream_io (dtp))
|
||||||
{
|
{
|
||||||
if (dtp->u.p.current_unit->strm_pos - 1
|
|
||||||
!= file_position (dtp->u.p.current_unit->s)
|
|
||||||
&& sseek (dtp->u.p.current_unit->s,
|
|
||||||
dtp->u.p.current_unit->strm_pos - 1) == FAILURE)
|
|
||||||
{
|
|
||||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (swrite (dtp->u.p.current_unit->s, buf, &nbytes) != 0)
|
if (swrite (dtp->u.p.current_unit->s, buf, &nbytes) != 0)
|
||||||
{
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
||||||
|
|
@ -866,7 +853,7 @@ static void
|
||||||
write_constant_string (st_parameter_dt *dtp, const fnode *f)
|
write_constant_string (st_parameter_dt *dtp, const fnode *f)
|
||||||
{
|
{
|
||||||
char c, delimiter, *p, *q;
|
char c, delimiter, *p, *q;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
length = f->u.string.length;
|
length = f->u.string.length;
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
|
|
@ -875,7 +862,7 @@ write_constant_string (st_parameter_dt *dtp, const fnode *f)
|
||||||
p = write_block (dtp, length);
|
p = write_block (dtp, length);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
q = f->u.string.p;
|
q = f->u.string.p;
|
||||||
delimiter = q[-1];
|
delimiter = q[-1];
|
||||||
|
|
||||||
|
|
@ -993,7 +980,10 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int len,
|
||||||
}
|
}
|
||||||
if (dtp->u.p.skips < 0)
|
if (dtp->u.p.skips < 0)
|
||||||
{
|
{
|
||||||
move_pos_offset (dtp->u.p.current_unit->s, dtp->u.p.skips);
|
if (is_internal_unit (dtp))
|
||||||
|
move_pos_offset (dtp->u.p.current_unit->s, dtp->u.p.skips);
|
||||||
|
else
|
||||||
|
fbuf_seek (dtp->u.p.current_unit, dtp->u.p.skips);
|
||||||
dtp->u.p.current_unit->bytes_left -= (gfc_offset) dtp->u.p.skips;
|
dtp->u.p.current_unit->bytes_left -= (gfc_offset) dtp->u.p.skips;
|
||||||
}
|
}
|
||||||
dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
|
dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
|
||||||
|
|
@ -1606,9 +1596,7 @@ transfer_array (st_parameter_dt *dtp, gfc_array_char *desc, int kind,
|
||||||
static void
|
static void
|
||||||
us_read (st_parameter_dt *dtp, int continued)
|
us_read (st_parameter_dt *dtp, int continued)
|
||||||
{
|
{
|
||||||
char *p;
|
size_t n, nr;
|
||||||
int n;
|
|
||||||
int nr;
|
|
||||||
GFC_INTEGER_4 i4;
|
GFC_INTEGER_4 i4;
|
||||||
GFC_INTEGER_8 i8;
|
GFC_INTEGER_8 i8;
|
||||||
gfc_offset i;
|
gfc_offset i;
|
||||||
|
|
@ -1623,7 +1611,11 @@ us_read (st_parameter_dt *dtp, int continued)
|
||||||
|
|
||||||
nr = n;
|
nr = n;
|
||||||
|
|
||||||
p = salloc_r (dtp->u.p.current_unit->s, &n);
|
if (sread (dtp->u.p.current_unit->s, &i, &n) != 0)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_BAD_US, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1631,7 +1623,7 @@ us_read (st_parameter_dt *dtp, int continued)
|
||||||
return; /* end of file */
|
return; /* end of file */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == NULL || n != nr)
|
if (n != nr)
|
||||||
{
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_BAD_US, NULL);
|
generate_error (&dtp->common, LIBERROR_BAD_US, NULL);
|
||||||
return;
|
return;
|
||||||
|
|
@ -1643,12 +1635,12 @@ us_read (st_parameter_dt *dtp, int continued)
|
||||||
switch (nr)
|
switch (nr)
|
||||||
{
|
{
|
||||||
case sizeof(GFC_INTEGER_4):
|
case sizeof(GFC_INTEGER_4):
|
||||||
memcpy (&i4, p, sizeof (i4));
|
memcpy (&i4, &i, sizeof (i4));
|
||||||
i = i4;
|
i = i4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sizeof(GFC_INTEGER_8):
|
case sizeof(GFC_INTEGER_8):
|
||||||
memcpy (&i8, p, sizeof (i8));
|
memcpy (&i8, &i, sizeof (i8));
|
||||||
i = i8;
|
i = i8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -1661,12 +1653,12 @@ us_read (st_parameter_dt *dtp, int continued)
|
||||||
switch (nr)
|
switch (nr)
|
||||||
{
|
{
|
||||||
case sizeof(GFC_INTEGER_4):
|
case sizeof(GFC_INTEGER_4):
|
||||||
reverse_memcpy (&i4, p, sizeof (i4));
|
reverse_memcpy (&i4, &i, sizeof (i4));
|
||||||
i = i4;
|
i = i4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sizeof(GFC_INTEGER_8):
|
case sizeof(GFC_INTEGER_8):
|
||||||
reverse_memcpy (&i8, p, sizeof (i8));
|
reverse_memcpy (&i8, &i, sizeof (i8));
|
||||||
i = i8;
|
i = i8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -1734,10 +1726,10 @@ pre_position (st_parameter_dt *dtp)
|
||||||
{
|
{
|
||||||
case FORMATTED_STREAM:
|
case FORMATTED_STREAM:
|
||||||
case UNFORMATTED_STREAM:
|
case UNFORMATTED_STREAM:
|
||||||
/* There are no records with stream I/O. Set the default position
|
/* There are no records with stream I/O. If the position was specified
|
||||||
to the beginning of the file if no position was specified. */
|
data_transfer_init has already positioned the file. If no position
|
||||||
if ((dtp->common.flags & IOPARM_DT_HAS_REC) == 0)
|
was specified, we continue from where we last left off. I.e.
|
||||||
dtp->u.p.current_unit->strm_pos = 1;
|
there is nothing to do here. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNFORMATTED_SEQUENTIAL:
|
case UNFORMATTED_SEQUENTIAL:
|
||||||
|
|
@ -2070,7 +2062,10 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
|
||||||
if (dtp->u.p.mode == READING
|
if (dtp->u.p.mode == READING
|
||||||
&& dtp->u.p.current_unit->mode == WRITING
|
&& dtp->u.p.current_unit->mode == WRITING
|
||||||
&& !is_internal_unit (dtp))
|
&& !is_internal_unit (dtp))
|
||||||
flush(dtp->u.p.current_unit->s);
|
{
|
||||||
|
fbuf_flush (dtp->u.p.current_unit, 1);
|
||||||
|
flush(dtp->u.p.current_unit->s);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check whether the record exists to be read. Only
|
/* Check whether the record exists to be read. Only
|
||||||
a partial record needs to exist. */
|
a partial record needs to exist. */
|
||||||
|
|
@ -2094,11 +2089,21 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dtp->u.p.current_unit->strm_pos = dtp->rec;
|
{
|
||||||
|
if (dtp->u.p.current_unit->strm_pos != dtp->rec)
|
||||||
|
{
|
||||||
|
fbuf_flush (dtp->u.p.current_unit, 1);
|
||||||
|
flush (dtp->u.p.current_unit->s);
|
||||||
|
if (sseek (dtp->u.p.current_unit->s, dtp->rec - 1) == FAILURE)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dtp->u.p.current_unit->strm_pos = dtp->rec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
dtp->rec = 0;
|
|
||||||
|
|
||||||
/* Overwriting an existing sequential file ?
|
/* Overwriting an existing sequential file ?
|
||||||
it is always safe to truncate the file on the first write */
|
it is always safe to truncate the file on the first write */
|
||||||
|
|
@ -2118,6 +2123,7 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
|
||||||
dtp->u.p.max_pos = dtp->u.p.current_unit->saved_pos;
|
dtp->u.p.max_pos = dtp->u.p.current_unit->saved_pos;
|
||||||
|
|
||||||
pre_position (dtp);
|
pre_position (dtp);
|
||||||
|
|
||||||
|
|
||||||
/* Set up the subroutine that will handle the transfers. */
|
/* Set up the subroutine that will handle the transfers. */
|
||||||
|
|
||||||
|
|
@ -2256,14 +2262,13 @@ next_array_record (st_parameter_dt *dtp, array_loop_spec *ls, int *finished)
|
||||||
read chunks of size MAX_READ until we get to the right
|
read chunks of size MAX_READ until we get to the right
|
||||||
position. */
|
position. */
|
||||||
|
|
||||||
#define MAX_READ 4096
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
skip_record (st_parameter_dt *dtp, size_t bytes)
|
skip_record (st_parameter_dt *dtp, size_t bytes)
|
||||||
{
|
{
|
||||||
gfc_offset new;
|
gfc_offset new;
|
||||||
int rlength, length;
|
size_t rlength;
|
||||||
char *p;
|
static const size_t MAX_READ = 4096;
|
||||||
|
char p[MAX_READ];
|
||||||
|
|
||||||
dtp->u.p.current_unit->bytes_left_subrecord += bytes;
|
dtp->u.p.current_unit->bytes_left_subrecord += bytes;
|
||||||
if (dtp->u.p.current_unit->bytes_left_subrecord == 0)
|
if (dtp->u.p.current_unit->bytes_left_subrecord == 0)
|
||||||
|
|
@ -2283,24 +2288,22 @@ skip_record (st_parameter_dt *dtp, size_t bytes)
|
||||||
{ /* Seek by reading data. */
|
{ /* Seek by reading data. */
|
||||||
while (dtp->u.p.current_unit->bytes_left_subrecord > 0)
|
while (dtp->u.p.current_unit->bytes_left_subrecord > 0)
|
||||||
{
|
{
|
||||||
rlength = length =
|
rlength =
|
||||||
(MAX_READ > dtp->u.p.current_unit->bytes_left_subrecord) ?
|
(MAX_READ > (size_t) dtp->u.p.current_unit->bytes_left_subrecord) ?
|
||||||
MAX_READ : dtp->u.p.current_unit->bytes_left_subrecord;
|
MAX_READ : dtp->u.p.current_unit->bytes_left_subrecord;
|
||||||
|
|
||||||
p = salloc_r (dtp->u.p.current_unit->s, &rlength);
|
if (sread (dtp->u.p.current_unit->s, p, &rlength) != 0)
|
||||||
if (p == NULL)
|
|
||||||
{
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dtp->u.p.current_unit->bytes_left_subrecord -= length;
|
dtp->u.p.current_unit->bytes_left_subrecord -= rlength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef MAX_READ
|
|
||||||
|
|
||||||
/* Advance to the next record reading unformatted files, taking
|
/* Advance to the next record reading unformatted files, taking
|
||||||
care of subrecords. If complete_record is nonzero, we loop
|
care of subrecords. If complete_record is nonzero, we loop
|
||||||
|
|
@ -2328,14 +2331,23 @@ next_record_r_unf (st_parameter_dt *dtp, int complete_record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline gfc_offset
|
||||||
|
min_off (gfc_offset a, gfc_offset b)
|
||||||
|
{
|
||||||
|
return (a < b ? a : b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Space to the next record for read mode. */
|
/* Space to the next record for read mode. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
next_record_r (st_parameter_dt *dtp)
|
next_record_r (st_parameter_dt *dtp)
|
||||||
{
|
{
|
||||||
gfc_offset record;
|
gfc_offset record;
|
||||||
int length, bytes_left;
|
int bytes_left;
|
||||||
char *p;
|
size_t length;
|
||||||
|
char p;
|
||||||
|
|
||||||
switch (current_mode (dtp))
|
switch (current_mode (dtp))
|
||||||
{
|
{
|
||||||
|
|
@ -2384,18 +2396,24 @@ next_record_r (st_parameter_dt *dtp)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bytes_left = (int) dtp->u.p.current_unit->bytes_left;
|
bytes_left = (int) dtp->u.p.current_unit->bytes_left;
|
||||||
p = salloc_r (dtp->u.p.current_unit->s, &bytes_left);
|
bytes_left = min_off (bytes_left,
|
||||||
if (p != NULL)
|
file_length (dtp->u.p.current_unit->s)
|
||||||
dtp->u.p.current_unit->bytes_left
|
- file_position (dtp->u.p.current_unit->s));
|
||||||
= dtp->u.p.current_unit->recl;
|
if (sseek (dtp->u.p.current_unit->s,
|
||||||
|
file_position (dtp->u.p.current_unit->s)
|
||||||
|
+ bytes_left) == FAILURE)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dtp->u.p.current_unit->bytes_left
|
||||||
|
= dtp->u.p.current_unit->recl;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else do
|
else do
|
||||||
{
|
{
|
||||||
p = salloc_r (dtp->u.p.current_unit->s, &length);
|
if (sread (dtp->u.p.current_unit->s, &p, &length) != 0)
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
{
|
||||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2410,7 +2428,7 @@ next_record_r (st_parameter_dt *dtp)
|
||||||
if (is_stream_io (dtp))
|
if (is_stream_io (dtp))
|
||||||
dtp->u.p.current_unit->strm_pos++;
|
dtp->u.p.current_unit->strm_pos++;
|
||||||
}
|
}
|
||||||
while (*p != '\n');
|
while (p != '\n');
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2550,8 +2568,10 @@ next_record_w (st_parameter_dt *dtp, int done)
|
||||||
{
|
{
|
||||||
gfc_offset m, record, max_pos;
|
gfc_offset m, record, max_pos;
|
||||||
int length;
|
int length;
|
||||||
char *p;
|
|
||||||
|
|
||||||
|
/* Flush and reset the format buffer. */
|
||||||
|
fbuf_flush (dtp->u.p.current_unit, 1);
|
||||||
|
|
||||||
/* Zero counters for X- and T-editing. */
|
/* Zero counters for X- and T-editing. */
|
||||||
max_pos = dtp->u.p.max_pos;
|
max_pos = dtp->u.p.max_pos;
|
||||||
dtp->u.p.max_pos = dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
|
dtp->u.p.max_pos = dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
|
||||||
|
|
@ -2576,12 +2596,9 @@ next_record_w (st_parameter_dt *dtp, int done)
|
||||||
if (dtp->u.p.current_unit->bytes_left > 0)
|
if (dtp->u.p.current_unit->bytes_left > 0)
|
||||||
{
|
{
|
||||||
length = (int) dtp->u.p.current_unit->bytes_left;
|
length = (int) dtp->u.p.current_unit->bytes_left;
|
||||||
p = salloc_w (dtp->u.p.current_unit->s, &length);
|
if (sset (dtp->u.p.current_unit->s, 0, length) == FAILURE)
|
||||||
memset (p, 0, length);
|
goto io_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sfree (dtp->u.p.current_unit->s) == FAILURE)
|
|
||||||
goto io_error;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNFORMATTED_SEQUENTIAL:
|
case UNFORMATTED_SEQUENTIAL:
|
||||||
|
|
@ -2609,7 +2626,13 @@ next_record_w (st_parameter_dt *dtp, int done)
|
||||||
if (max_pos > m)
|
if (max_pos > m)
|
||||||
{
|
{
|
||||||
length = (int) (max_pos - m);
|
length = (int) (max_pos - m);
|
||||||
p = salloc_w (dtp->u.p.current_unit->s, &length);
|
if (sseek (dtp->u.p.current_unit->s,
|
||||||
|
file_position (dtp->u.p.current_unit->s)
|
||||||
|
+ length) == FAILURE)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
length = (int) (dtp->u.p.current_unit->recl - max_pos);
|
length = (int) (dtp->u.p.current_unit->recl - max_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2651,7 +2674,13 @@ next_record_w (st_parameter_dt *dtp, int done)
|
||||||
if (max_pos > m)
|
if (max_pos > m)
|
||||||
{
|
{
|
||||||
length = (int) (max_pos - m);
|
length = (int) (max_pos - m);
|
||||||
p = salloc_w (dtp->u.p.current_unit->s, &length);
|
if (sseek (dtp->u.p.current_unit->s,
|
||||||
|
file_position (dtp->u.p.current_unit->s)
|
||||||
|
+ length) == FAILURE)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
length = (int) (dtp->u.p.current_unit->recl - max_pos);
|
length = (int) (dtp->u.p.current_unit->recl - max_pos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2670,15 +2699,6 @@ next_record_w (st_parameter_dt *dtp, int done)
|
||||||
size_t len;
|
size_t len;
|
||||||
const char crlf[] = "\r\n";
|
const char crlf[] = "\r\n";
|
||||||
|
|
||||||
/* Move to the farthest position reached in preparation for
|
|
||||||
completing the record. (for file unit) */
|
|
||||||
m = dtp->u.p.current_unit->recl -
|
|
||||||
dtp->u.p.current_unit->bytes_left;
|
|
||||||
if (max_pos > m)
|
|
||||||
{
|
|
||||||
length = (int) (max_pos - m);
|
|
||||||
p = salloc_w (dtp->u.p.current_unit->s, &length);
|
|
||||||
}
|
|
||||||
#ifdef HAVE_CRLF
|
#ifdef HAVE_CRLF
|
||||||
len = 2;
|
len = 2;
|
||||||
#else
|
#else
|
||||||
|
|
@ -2818,6 +2838,7 @@ finalize_transfer (st_parameter_dt *dtp)
|
||||||
if (!is_internal_unit (dtp) && dtp->u.p.seen_dollar)
|
if (!is_internal_unit (dtp) && dtp->u.p.seen_dollar)
|
||||||
{
|
{
|
||||||
dtp->u.p.seen_dollar = 0;
|
dtp->u.p.seen_dollar = 0;
|
||||||
|
fbuf_flush (dtp->u.p.current_unit, 1);
|
||||||
sfree (dtp->u.p.current_unit->s);
|
sfree (dtp->u.p.current_unit->s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2830,6 +2851,7 @@ finalize_transfer (st_parameter_dt *dtp)
|
||||||
- dtp->u.p.current_unit->bytes_left);
|
- dtp->u.p.current_unit->bytes_left);
|
||||||
dtp->u.p.current_unit->saved_pos =
|
dtp->u.p.current_unit->saved_pos =
|
||||||
dtp->u.p.max_pos > 0 ? dtp->u.p.max_pos - bytes_written : 0;
|
dtp->u.p.max_pos > 0 ? dtp->u.p.max_pos - bytes_written : 0;
|
||||||
|
fbuf_flush (dtp->u.p.current_unit, 0);
|
||||||
flush (dtp->u.p.current_unit->s);
|
flush (dtp->u.p.current_unit->s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -567,6 +567,8 @@ init_units (void)
|
||||||
u->file_len = strlen (stdout_name);
|
u->file_len = strlen (stdout_name);
|
||||||
u->file = get_mem (u->file_len);
|
u->file = get_mem (u->file_len);
|
||||||
memmove (u->file, stdout_name, u->file_len);
|
memmove (u->file, stdout_name, u->file_len);
|
||||||
|
|
||||||
|
fbuf_init (u, 0);
|
||||||
|
|
||||||
__gthread_mutex_unlock (&u->lock);
|
__gthread_mutex_unlock (&u->lock);
|
||||||
}
|
}
|
||||||
|
|
@ -594,6 +596,9 @@ init_units (void)
|
||||||
u->file_len = strlen (stderr_name);
|
u->file_len = strlen (stderr_name);
|
||||||
u->file = get_mem (u->file_len);
|
u->file = get_mem (u->file_len);
|
||||||
memmove (u->file, stderr_name, u->file_len);
|
memmove (u->file, stderr_name, u->file_len);
|
||||||
|
|
||||||
|
fbuf_init (u, 256); /* 256 bytes should be enough, probably not doing
|
||||||
|
any kind of exotic formatting to stderr. */
|
||||||
|
|
||||||
__gthread_mutex_unlock (&u->lock);
|
__gthread_mutex_unlock (&u->lock);
|
||||||
}
|
}
|
||||||
|
|
@ -613,7 +618,7 @@ static int
|
||||||
close_unit_1 (gfc_unit *u, int locked)
|
close_unit_1 (gfc_unit *u, int locked)
|
||||||
{
|
{
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
|
||||||
/* If there are previously written bytes from a write with ADVANCE="no"
|
/* If there are previously written bytes from a write with ADVANCE="no"
|
||||||
Reposition the buffer before closing. */
|
Reposition the buffer before closing. */
|
||||||
if (u->previous_nonadvancing_write)
|
if (u->previous_nonadvancing_write)
|
||||||
|
|
@ -635,6 +640,8 @@ close_unit_1 (gfc_unit *u, int locked)
|
||||||
free_mem (u->file);
|
free_mem (u->file);
|
||||||
u->file = NULL;
|
u->file = NULL;
|
||||||
u->file_len = 0;
|
u->file_len = 0;
|
||||||
|
|
||||||
|
fbuf_destroy (u);
|
||||||
|
|
||||||
if (!locked)
|
if (!locked)
|
||||||
__gthread_mutex_unlock (&u->lock);
|
__gthread_mutex_unlock (&u->lock);
|
||||||
|
|
@ -737,10 +744,11 @@ filename_from_unit (int n)
|
||||||
void
|
void
|
||||||
finish_last_advance_record (gfc_unit *u)
|
finish_last_advance_record (gfc_unit *u)
|
||||||
{
|
{
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (u->saved_pos > 0)
|
if (u->saved_pos > 0)
|
||||||
p = salloc_w (u->s, &u->saved_pos);
|
fbuf_seek (u, u->saved_pos);
|
||||||
|
|
||||||
|
fbuf_flush (u, 1);
|
||||||
|
|
||||||
if (!(u->unit_number == options.stdout_unit
|
if (!(u->unit_number == options.stdout_unit
|
||||||
|| u->unit_number == options.stderr_unit))
|
|| u->unit_number == options.stderr_unit))
|
||||||
|
|
|
||||||
|
|
@ -530,12 +530,10 @@ fd_alloc (unix_stream * s, gfc_offset where,
|
||||||
* NULL on I/O error. */
|
* NULL on I/O error. */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
|
fd_alloc_r_at (unix_stream * s, int *len)
|
||||||
{
|
{
|
||||||
gfc_offset m;
|
gfc_offset m;
|
||||||
|
gfc_offset where = s->logical_offset;
|
||||||
if (where == -1)
|
|
||||||
where = s->logical_offset;
|
|
||||||
|
|
||||||
if (s->buffer != NULL && s->buffer_offset <= where &&
|
if (s->buffer != NULL && s->buffer_offset <= where &&
|
||||||
where + *len <= s->buffer_offset + s->active)
|
where + *len <= s->buffer_offset + s->active)
|
||||||
|
|
@ -593,12 +591,10 @@ fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
|
||||||
* we've already buffered the data or we need to load it. */
|
* we've already buffered the data or we need to load it. */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
|
fd_alloc_w_at (unix_stream * s, int *len)
|
||||||
{
|
{
|
||||||
gfc_offset n;
|
gfc_offset n;
|
||||||
|
gfc_offset where = s->logical_offset;
|
||||||
if (where == -1)
|
|
||||||
where = s->logical_offset;
|
|
||||||
|
|
||||||
if (s->buffer == NULL || s->buffer_offset > where ||
|
if (s->buffer == NULL || s->buffer_offset > where ||
|
||||||
where + *len > s->buffer_offset + s->len)
|
where + *len > s->buffer_offset + s->len)
|
||||||
|
|
@ -752,7 +748,7 @@ fd_sset (unix_stream * s, int c, size_t n)
|
||||||
/* memset() in chunks of BUFFER_SIZE. */
|
/* memset() in chunks of BUFFER_SIZE. */
|
||||||
trans = (bytes_left < BUFFER_SIZE) ? bytes_left : BUFFER_SIZE;
|
trans = (bytes_left < BUFFER_SIZE) ? bytes_left : BUFFER_SIZE;
|
||||||
|
|
||||||
p = fd_alloc_w_at (s, &trans, -1);
|
p = fd_alloc_w_at (s, &trans);
|
||||||
if (p)
|
if (p)
|
||||||
memset (p, c, trans);
|
memset (p, c, trans);
|
||||||
else
|
else
|
||||||
|
|
@ -779,7 +775,7 @@ fd_read (unix_stream * s, void * buf, size_t * nbytes)
|
||||||
if (*nbytes < BUFFER_SIZE && s->method == SYNC_BUFFERED)
|
if (*nbytes < BUFFER_SIZE && s->method == SYNC_BUFFERED)
|
||||||
{
|
{
|
||||||
tmp = *nbytes;
|
tmp = *nbytes;
|
||||||
p = fd_alloc_r_at (s, &tmp, -1);
|
p = fd_alloc_r_at (s, &tmp);
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
*nbytes = tmp;
|
*nbytes = tmp;
|
||||||
|
|
@ -827,7 +823,7 @@ fd_write (unix_stream * s, const void * buf, size_t * nbytes)
|
||||||
if (*nbytes < BUFFER_SIZE && s->method == SYNC_BUFFERED)
|
if (*nbytes < BUFFER_SIZE && s->method == SYNC_BUFFERED)
|
||||||
{
|
{
|
||||||
tmp = *nbytes;
|
tmp = *nbytes;
|
||||||
p = fd_alloc_w_at (s, &tmp, -1);
|
p = fd_alloc_w_at (s, &tmp);
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
*nbytes = tmp;
|
*nbytes = tmp;
|
||||||
|
|
@ -890,7 +886,6 @@ fd_open (unix_stream * s)
|
||||||
else
|
else
|
||||||
s->method = SYNC_BUFFERED;
|
s->method = SYNC_BUFFERED;
|
||||||
|
|
||||||
s->st.alloc_r_at = (void *) fd_alloc_r_at;
|
|
||||||
s->st.alloc_w_at = (void *) fd_alloc_w_at;
|
s->st.alloc_w_at = (void *) fd_alloc_w_at;
|
||||||
s->st.sfree = (void *) fd_sfree;
|
s->st.sfree = (void *) fd_sfree;
|
||||||
s->st.close = (void *) fd_close;
|
s->st.close = (void *) fd_close;
|
||||||
|
|
@ -918,12 +913,10 @@ fd_open (unix_stream * s)
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
mem_alloc_r_at (int_stream * s, int *len, gfc_offset where)
|
mem_alloc_r_at (int_stream * s, int *len)
|
||||||
{
|
{
|
||||||
gfc_offset n;
|
gfc_offset n;
|
||||||
|
gfc_offset where = s->logical_offset;
|
||||||
if (where == -1)
|
|
||||||
where = s->logical_offset;
|
|
||||||
|
|
||||||
if (where < s->buffer_offset || where > s->buffer_offset + s->active)
|
if (where < s->buffer_offset || where > s->buffer_offset + s->active)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -939,15 +932,13 @@ mem_alloc_r_at (int_stream * s, int *len, gfc_offset where)
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
mem_alloc_w_at (int_stream * s, int *len, gfc_offset where)
|
mem_alloc_w_at (int_stream * s, int *len)
|
||||||
{
|
{
|
||||||
gfc_offset m;
|
gfc_offset m;
|
||||||
|
gfc_offset where = s->logical_offset;
|
||||||
|
|
||||||
assert (*len >= 0); /* Negative values not allowed. */
|
assert (*len >= 0); /* Negative values not allowed. */
|
||||||
|
|
||||||
if (where == -1)
|
|
||||||
where = s->logical_offset;
|
|
||||||
|
|
||||||
m = where + *len;
|
m = where + *len;
|
||||||
|
|
||||||
if (where < s->buffer_offset)
|
if (where < s->buffer_offset)
|
||||||
|
|
@ -962,9 +953,7 @@ mem_alloc_w_at (int_stream * s, int *len, gfc_offset where)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Stream read function for internal units. This is not actually used
|
/* Stream read function for internal units. */
|
||||||
at the moment, as all internal IO is formatted and the formatted IO
|
|
||||||
routines use mem_alloc_r_at. */
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mem_read (int_stream * s, void * buf, size_t * nbytes)
|
mem_read (int_stream * s, void * buf, size_t * nbytes)
|
||||||
|
|
@ -973,7 +962,7 @@ mem_read (int_stream * s, void * buf, size_t * nbytes)
|
||||||
int tmp;
|
int tmp;
|
||||||
|
|
||||||
tmp = *nbytes;
|
tmp = *nbytes;
|
||||||
p = mem_alloc_r_at (s, &tmp, -1);
|
p = mem_alloc_r_at (s, &tmp);
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
*nbytes = tmp;
|
*nbytes = tmp;
|
||||||
|
|
@ -983,7 +972,7 @@ mem_read (int_stream * s, void * buf, size_t * nbytes)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*nbytes = 0;
|
*nbytes = 0;
|
||||||
return errno;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -998,10 +987,8 @@ mem_write (int_stream * s, const void * buf, size_t * nbytes)
|
||||||
void *p;
|
void *p;
|
||||||
int tmp;
|
int tmp;
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
|
|
||||||
tmp = *nbytes;
|
tmp = *nbytes;
|
||||||
p = mem_alloc_w_at (s, &tmp, -1);
|
p = mem_alloc_w_at (s, &tmp);
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
*nbytes = tmp;
|
*nbytes = tmp;
|
||||||
|
|
@ -1011,7 +998,7 @@ mem_write (int_stream * s, const void * buf, size_t * nbytes)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*nbytes = 0;
|
*nbytes = 0;
|
||||||
return errno;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1038,7 +1025,7 @@ mem_set (int_stream * s, int c, size_t n)
|
||||||
|
|
||||||
len = n;
|
len = n;
|
||||||
|
|
||||||
p = mem_alloc_w_at (s, &len, -1);
|
p = mem_alloc_w_at (s, &len);
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
memset (p, c, len);
|
memset (p, c, len);
|
||||||
|
|
@ -1104,7 +1091,6 @@ open_internal (char *base, int length, gfc_offset offset)
|
||||||
s->logical_offset = 0;
|
s->logical_offset = 0;
|
||||||
s->active = s->file_length = length;
|
s->active = s->file_length = length;
|
||||||
|
|
||||||
s->st.alloc_r_at = (void *) mem_alloc_r_at;
|
|
||||||
s->st.alloc_w_at = (void *) mem_alloc_w_at;
|
s->st.alloc_w_at = (void *) mem_alloc_w_at;
|
||||||
s->st.sfree = (void *) mem_sfree;
|
s->st.sfree = (void *) mem_sfree;
|
||||||
s->st.close = (void *) mem_close;
|
s->st.close = (void *) mem_close;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue