aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/libgfortran/io
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/libgfortran/io')
-rw-r--r--gcc-4.8.1/libgfortran/io/close.c102
-rw-r--r--gcc-4.8.1/libgfortran/io/fbuf.c269
-rw-r--r--gcc-4.8.1/libgfortran/io/fbuf.h86
-rw-r--r--gcc-4.8.1/libgfortran/io/file_pos.c463
-rw-r--r--gcc-4.8.1/libgfortran/io/format.c1401
-rw-r--r--gcc-4.8.1/libgfortran/io/format.h144
-rw-r--r--gcc-4.8.1/libgfortran/io/inquire.c743
-rw-r--r--gcc-4.8.1/libgfortran/io/intrinsics.c416
-rw-r--r--gcc-4.8.1/libgfortran/io/io.h811
-rw-r--r--gcc-4.8.1/libgfortran/io/list_read.c3155
-rw-r--r--gcc-4.8.1/libgfortran/io/lock.c66
-rw-r--r--gcc-4.8.1/libgfortran/io/open.c868
-rw-r--r--gcc-4.8.1/libgfortran/io/read.c1248
-rw-r--r--gcc-4.8.1/libgfortran/io/size_from_kind.c83
-rw-r--r--gcc-4.8.1/libgfortran/io/transfer.c3865
-rw-r--r--gcc-4.8.1/libgfortran/io/transfer128.c97
-rw-r--r--gcc-4.8.1/libgfortran/io/unit.c838
-rw-r--r--gcc-4.8.1/libgfortran/io/unix.c1884
-rw-r--r--gcc-4.8.1/libgfortran/io/unix.h189
-rw-r--r--gcc-4.8.1/libgfortran/io/write.c2006
-rw-r--r--gcc-4.8.1/libgfortran/io/write_float.def1268
21 files changed, 0 insertions, 20002 deletions
diff --git a/gcc-4.8.1/libgfortran/io/close.c b/gcc-4.8.1/libgfortran/io/close.c
deleted file mode 100644
index fa9c1137f..000000000
--- a/gcc-4.8.1/libgfortran/io/close.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
-
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "io.h"
-#include "unix.h"
-#include <limits.h>
-
-typedef enum
-{ CLOSE_DELETE, CLOSE_KEEP, CLOSE_UNSPECIFIED }
-close_status;
-
-static const st_option status_opt[] = {
- {"keep", CLOSE_KEEP},
- {"delete", CLOSE_DELETE},
- {NULL, 0}
-};
-
-
-extern void st_close (st_parameter_close *);
-export_proto(st_close);
-
-void
-st_close (st_parameter_close *clp)
-{
- close_status status;
- gfc_unit *u;
-#if !HAVE_UNLINK_OPEN_FILE
- char * path;
-
- path = NULL;
-#endif
-
- library_start (&clp->common);
-
- status = !(clp->common.flags & IOPARM_CLOSE_HAS_STATUS) ? CLOSE_UNSPECIFIED :
- find_option (&clp->common, clp->status, clp->status_len,
- status_opt, "Bad STATUS parameter in CLOSE statement");
-
- if ((clp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- {
- library_end ();
- return;
- }
-
- u = find_unit (clp->common.unit);
- if (u != NULL)
- {
- if (u->flags.status == STATUS_SCRATCH)
- {
- if (status == CLOSE_KEEP)
- generate_error (&clp->common, LIBERROR_BAD_OPTION,
- "Can't KEEP a scratch file on CLOSE");
-#if !HAVE_UNLINK_OPEN_FILE
- path = (char *) gfc_alloca (u->file_len + 1);
- unpack_filename (path, u->file, u->file_len);
-#endif
- }
- else
- {
- if (status == CLOSE_DELETE)
- {
-#if HAVE_UNLINK_OPEN_FILE
- delete_file (u);
-#else
- path = (char *) gfc_alloca (u->file_len + 1);
- unpack_filename (path, u->file, u->file_len);
-#endif
- }
- }
-
- close_unit (u);
-
-#if !HAVE_UNLINK_OPEN_FILE
- if (path != NULL)
- unlink (path);
-#endif
- }
-
- /* CLOSE on unconnected unit is legal and a no-op: F95 std., 9.3.5. */
- library_end ();
-}
diff --git a/gcc-4.8.1/libgfortran/io/fbuf.c b/gcc-4.8.1/libgfortran/io/fbuf.c
deleted file mode 100644
index ace990db8..000000000
--- a/gcc-4.8.1/libgfortran/io/fbuf.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
- Contributed by Janne Blomqvist
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-
-#include "io.h"
-#include "fbuf.h"
-#include "unix.h"
-#include <string.h>
-#include <stdlib.h>
-
-
-//#define FBUF_DEBUG
-
-
-void
-fbuf_init (gfc_unit * u, int len)
-{
- if (len == 0)
- len = 512; /* Default size. */
-
- u->fbuf = xmalloc (sizeof (struct fbuf));
- u->fbuf->buf = xmalloc (len);
- u->fbuf->len = len;
- u->fbuf->act = u->fbuf->pos = 0;
-}
-
-
-void
-fbuf_destroy (gfc_unit * u)
-{
- if (u->fbuf == NULL)
- return;
- free (u->fbuf->buf);
- free (u->fbuf);
- u->fbuf = NULL;
-}
-
-
-static void
-#ifdef FBUF_DEBUG
-fbuf_debug (gfc_unit * u, const char * format, ...)
-{
- va_list args;
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- fprintf (stderr, "fbuf_debug pos: %d, act: %d, buf: ''",
- u->fbuf->pos, u->fbuf->act);
- for (int ii = 0; ii < u->fbuf->act; ii++)
- {
- putc (u->fbuf->buf[ii], stderr);
- }
- fprintf (stderr, "''\n");
-}
-#else
-fbuf_debug (gfc_unit * u __attribute__ ((unused)),
- const char * format __attribute__ ((unused)),
- ...) {}
-#endif
-
-
-
-/* You should probably call this before doing a physical seek on the
- underlying device. Returns how much the physical position was
- modified. */
-
-int
-fbuf_reset (gfc_unit * u)
-{
- int seekval = 0;
-
- if (!u->fbuf)
- return 0;
-
- fbuf_debug (u, "fbuf_reset: ");
- fbuf_flush (u, u->mode);
- /* If we read past the current position, seek the underlying device
- back. */
- if (u->mode == READING && u->fbuf->act > u->fbuf->pos)
- {
- seekval = - (u->fbuf->act - u->fbuf->pos);
- fbuf_debug (u, "fbuf_reset seekval %d, ", seekval);
- }
- u->fbuf->act = u->fbuf->pos = 0;
- return seekval;
-}
-
-
-/* Return a pointer to the current position in the buffer, and increase
- the pointer by len. Makes sure that the buffer is big enough,
- reallocating if necessary. */
-
-char *
-fbuf_alloc (gfc_unit * u, int len)
-{
- int newlen;
- char *dest;
- fbuf_debug (u, "fbuf_alloc len %d, ", len);
- if (u->fbuf->pos + len > u->fbuf->len)
- {
- /* Round up to nearest multiple of the current buffer length. */
- newlen = ((u->fbuf->pos + len) / u->fbuf->len + 1) * u->fbuf->len;
- dest = realloc (u->fbuf->buf, newlen);
- if (dest == NULL)
- return NULL;
- u->fbuf->buf = dest;
- u->fbuf->len = newlen;
- }
-
- dest = u->fbuf->buf + u->fbuf->pos;
- u->fbuf->pos += len;
- if (u->fbuf->pos > u->fbuf->act)
- u->fbuf->act = u->fbuf->pos;
- return dest;
-}
-
-
-/* mode argument is WRITING for write mode and READING for read
- mode. Return value is 0 for success, -1 on failure. */
-
-int
-fbuf_flush (gfc_unit * u, unit_mode mode)
-{
- int nwritten;
-
- if (!u->fbuf)
- return 0;
-
- fbuf_debug (u, "fbuf_flush with mode %d: ", mode);
-
- if (mode == WRITING)
- {
- if (u->fbuf->pos > 0)
- {
- nwritten = swrite (u->s, u->fbuf->buf, u->fbuf->pos);
- if (nwritten < 0)
- return -1;
- }
- }
- /* Salvage remaining bytes for both reading and writing. This
- happens with the combination of advance='no' and T edit
- descriptors leaving the final position somewhere not at the end
- of the record. For reading, this also happens if we sread() past
- the record boundary. */
- if (u->fbuf->act > u->fbuf->pos && u->fbuf->pos > 0)
- memmove (u->fbuf->buf, u->fbuf->buf + u->fbuf->pos,
- u->fbuf->act - u->fbuf->pos);
-
- u->fbuf->act -= u->fbuf->pos;
- u->fbuf->pos = 0;
-
- return 0;
-}
-
-
-int
-fbuf_seek (gfc_unit * u, int off, int whence)
-{
- if (!u->fbuf)
- return -1;
-
- switch (whence)
- {
- case SEEK_SET:
- break;
- case SEEK_CUR:
- off += u->fbuf->pos;
- break;
- case SEEK_END:
- off += u->fbuf->act;
- break;
- default:
- return -1;
- }
-
- fbuf_debug (u, "fbuf_seek, off %d ", off);
- /* The start of the buffer is always equal to the left tab
- limit. Moving to the left past the buffer is illegal in C and
- would also imply moving past the left tab limit, which is never
- allowed in Fortran. Similarly, seeking past the end of the buffer
- is not possible, in that case the user must make sure to allocate
- space with fbuf_alloc(). So return error if that is
- attempted. */
- if (off < 0 || off > u->fbuf->act)
- return -1;
- u->fbuf->pos = off;
- return off;
-}
-
-
-/* Fill the buffer with bytes for reading. Returns a pointer to start
- reading from. If we hit EOF, returns a short read count. If any
- other error occurs, return NULL. After reading, the caller is
- expected to call fbuf_seek to update the position with the number
- of bytes actually processed. */
-
-char *
-fbuf_read (gfc_unit * u, int * len)
-{
- char *ptr;
- int oldact, oldpos;
- int readlen = 0;
-
- fbuf_debug (u, "fbuf_read, len %d: ", *len);
- oldact = u->fbuf->act;
- oldpos = u->fbuf->pos;
- ptr = fbuf_alloc (u, *len);
- u->fbuf->pos = oldpos;
- if (oldpos + *len > oldact)
- {
- fbuf_debug (u, "reading %d bytes starting at %d ",
- oldpos + *len - oldact, oldact);
- readlen = sread (u->s, u->fbuf->buf + oldact, oldpos + *len - oldact);
- if (readlen < 0)
- return NULL;
- *len = oldact - oldpos + readlen;
- }
- u->fbuf->act = oldact + readlen;
- fbuf_debug (u, "fbuf_read done: ");
- return ptr;
-}
-
-
-/* When the fbuf_getc() inline function runs out of buffer space, it
- calls this function to fill the buffer with bytes for
- reading. Never call this function directly. */
-
-int
-fbuf_getc_refill (gfc_unit * u)
-{
- int nread;
- char *p;
-
- fbuf_debug (u, "fbuf_getc_refill ");
-
- /* Read 80 bytes (average line length?). This is a compromise
- between not needing to call the read() syscall all the time and
- not having to memmove unnecessary stuff when switching to the
- next record. */
- nread = 80;
-
- p = fbuf_read (u, &nread);
-
- if (p && nread > 0)
- return (unsigned char) u->fbuf->buf[u->fbuf->pos++];
- else
- return EOF;
-}
diff --git a/gcc-4.8.1/libgfortran/io/fbuf.h b/gcc-4.8.1/libgfortran/io/fbuf.h
deleted file mode 100644
index d125a2cf6..000000000
--- a/gcc-4.8.1/libgfortran/io/fbuf.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Copyright (C) 2009-2013 Free Software Foundation, Inc.
- Contributed by Janne Blomqvist
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef GFOR_FBUF_H
-#define GFOR_FBUF_H
-
-#include "io.h"
-
-
-/* Formatting buffer. This is a temporary scratch buffer used by
- formatted read and writes. After every formatted I/O 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. */
-
-struct fbuf
-{
- char *buf; /* Start of buffer. */
- int len; /* Length of buffer. */
- int act; /* Active bytes in buffer. */
- int pos; /* Current position in buffer. */
-};
-
-extern void fbuf_init (gfc_unit *, int);
-internal_proto(fbuf_init);
-
-extern void fbuf_destroy (gfc_unit *);
-internal_proto(fbuf_destroy);
-
-extern int fbuf_reset (gfc_unit *);
-internal_proto(fbuf_reset);
-
-extern char * fbuf_alloc (gfc_unit *, int);
-internal_proto(fbuf_alloc);
-
-extern int fbuf_flush (gfc_unit *, unit_mode);
-internal_proto(fbuf_flush);
-
-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);
-}
-
-static inline char *
-fbuf_getptr (gfc_unit * u)
-{
- return (char*) (u->fbuf->buf + u->fbuf->pos);
-}
-
-#endif
diff --git a/gcc-4.8.1/libgfortran/io/file_pos.c b/gcc-4.8.1/libgfortran/io/file_pos.c
deleted file mode 100644
index 8b4fda3dd..000000000
--- a/gcc-4.8.1/libgfortran/io/file_pos.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught and Janne Blomqvist
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "io.h"
-#include "fbuf.h"
-#include "unix.h"
-#include <string.h>
-
-/* file_pos.c-- Implement the file positioning statements, i.e. BACKSPACE,
- ENDFILE, and REWIND as well as the FLUSH statement. */
-
-
-/* formatted_backspace(fpp, u)-- Move the file back one line. The
- current position is after the newline that terminates the previous
- record, and we have to sift backwards to find the newline before
- that or the start of the file, whichever comes first. */
-
-static const int READ_CHUNK = 4096;
-
-static void
-formatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
-{
- gfc_offset base;
- char p[READ_CHUNK];
- ssize_t n;
-
- base = stell (u->s) - 1;
-
- do
- {
- n = (base < READ_CHUNK) ? base : READ_CHUNK;
- base -= n;
- if (sseek (u->s, base, SEEK_SET) < 0)
- goto io_error;
- if (sread (u->s, p, n) != n)
- goto io_error;
-
- /* We have moved backwards from the current position, it should
- not be possible to get a short read. Because it is not
- clear what to do about such thing, we ignore the possibility. */
-
- /* There is no memrchr() in the C library, so we have to do it
- ourselves. */
-
- while (n > 0)
- {
- n--;
- if (p[n] == '\n')
- {
- base += n + 1;
- goto done;
- }
- }
-
- }
- while (base != 0);
-
- /* base is the new pointer. Seek to it exactly. */
- done:
- if (sseek (u->s, base, SEEK_SET) < 0)
- goto io_error;
- u->last_record--;
- u->endfile = NO_ENDFILE;
-
- return;
-
- io_error:
- generate_error (&fpp->common, LIBERROR_OS, NULL);
-}
-
-
-/* unformatted_backspace(fpp) -- Move the file backwards for an unformatted
- sequential file. We are guaranteed to be between records on entry and
- we have to shift to the previous record. Loop over subrecords. */
-
-static void
-unformatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
-{
- gfc_offset m, slen;
- GFC_INTEGER_4 m4;
- GFC_INTEGER_8 m8;
- ssize_t length;
- int continued;
- char p[sizeof (GFC_INTEGER_8)];
-
- if (compile_options.record_marker == 0)
- length = sizeof (GFC_INTEGER_4);
- else
- length = compile_options.record_marker;
-
- do
- {
- slen = - (gfc_offset) length;
- if (sseek (u->s, slen, SEEK_CUR) < 0)
- goto io_error;
- if (sread (u->s, p, length) != length)
- goto io_error;
-
- /* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */
- if (likely (u->flags.convert == GFC_CONVERT_NATIVE))
- {
- switch (length)
- {
- case sizeof(GFC_INTEGER_4):
- memcpy (&m4, p, sizeof (m4));
- m = m4;
- break;
-
- case sizeof(GFC_INTEGER_8):
- memcpy (&m8, p, sizeof (m8));
- m = m8;
- break;
-
- default:
- runtime_error ("Illegal value for record marker");
- break;
- }
- }
- else
- {
- uint32_t u32;
- uint64_t u64;
- switch (length)
- {
- case sizeof(GFC_INTEGER_4):
- memcpy (&u32, p, sizeof (u32));
- u32 = __builtin_bswap32 (u32);
- memcpy (&m4, &u32, sizeof (m4));
- m = m4;
- break;
-
- case sizeof(GFC_INTEGER_8):
- memcpy (&u64, p, sizeof (u64));
- u64 = __builtin_bswap64 (u64);
- memcpy (&m8, &u64, sizeof (m8));
- m = m8;
- break;
-
- default:
- runtime_error ("Illegal value for record marker");
- break;
- }
-
- }
-
- continued = m < 0;
- if (continued)
- m = -m;
-
- if (sseek (u->s, -m -2 * length, SEEK_CUR) < 0)
- goto io_error;
- } while (continued);
-
- u->last_record--;
- return;
-
- io_error:
- generate_error (&fpp->common, LIBERROR_OS, NULL);
-}
-
-
-extern void st_backspace (st_parameter_filepos *);
-export_proto(st_backspace);
-
-void
-st_backspace (st_parameter_filepos *fpp)
-{
- gfc_unit *u;
-
- library_start (&fpp->common);
-
- u = find_unit (fpp->common.unit);
- if (u == NULL)
- {
- generate_error (&fpp->common, LIBERROR_BAD_UNIT, NULL);
- goto done;
- }
-
- /* Direct access is prohibited, and so is unformatted stream access. */
-
-
- if (u->flags.access == ACCESS_DIRECT)
- {
- generate_error (&fpp->common, LIBERROR_OPTION_CONFLICT,
- "Cannot BACKSPACE a file opened for DIRECT access");
- goto done;
- }
-
- if (u->flags.access == ACCESS_STREAM && u->flags.form == FORM_UNFORMATTED)
- {
- generate_error (&fpp->common, LIBERROR_OPTION_CONFLICT,
- "Cannot BACKSPACE an unformatted stream file");
- goto done;
- }
-
- /* Make sure format buffer is flushed and reset. */
- if (u->flags.form == FORM_FORMATTED)
- {
- int pos = fbuf_reset (u);
- if (pos != 0)
- sseek (u->s, pos, SEEK_CUR);
- }
-
-
- /* Check for special cases involving the ENDFILE record first. */
-
- if (u->endfile == AFTER_ENDFILE)
- {
- u->endfile = AT_ENDFILE;
- u->flags.position = POSITION_APPEND;
- sflush (u->s);
- }
- else
- {
- if (stell (u->s) == 0)
- {
- u->flags.position = POSITION_REWIND;
- goto done; /* Common special case */
- }
-
- if (u->mode == WRITING)
- {
- /* If there are previously written bytes from a write with
- ADVANCE="no", add a record marker before performing the
- BACKSPACE. */
-
- if (u->previous_nonadvancing_write)
- finish_last_advance_record (u);
-
- u->previous_nonadvancing_write = 0;
-
- unit_truncate (u, stell (u->s), &fpp->common);
- u->mode = READING;
- }
-
- if (u->flags.form == FORM_FORMATTED)
- formatted_backspace (fpp, u);
- else
- unformatted_backspace (fpp, u);
-
- u->flags.position = POSITION_UNSPECIFIED;
- u->endfile = NO_ENDFILE;
- u->current_record = 0;
- u->bytes_left = 0;
- }
-
- done:
- if (u != NULL)
- unlock_unit (u);
-
- library_end ();
-}
-
-
-extern void st_endfile (st_parameter_filepos *);
-export_proto(st_endfile);
-
-void
-st_endfile (st_parameter_filepos *fpp)
-{
- gfc_unit *u;
-
- library_start (&fpp->common);
-
- u = find_unit (fpp->common.unit);
- if (u != NULL)
- {
- if (u->flags.access == ACCESS_DIRECT)
- {
- generate_error (&fpp->common, LIBERROR_OPTION_CONFLICT,
- "Cannot perform ENDFILE on a file opened "
- "for DIRECT access");
- goto done;
- }
-
- if (u->flags.access == ACCESS_SEQUENTIAL
- && u->endfile == AFTER_ENDFILE)
- {
- generate_error (&fpp->common, LIBERROR_OPTION_CONFLICT,
- "Cannot perform ENDFILE on a file already "
- "positioned after the EOF marker");
- goto done;
- }
-
- /* If there are previously written bytes from a write with ADVANCE="no",
- add a record marker before performing the ENDFILE. */
-
- if (u->previous_nonadvancing_write)
- finish_last_advance_record (u);
-
- u->previous_nonadvancing_write = 0;
-
- if (u->current_record)
- {
- st_parameter_dt dtp;
- dtp.common = fpp->common;
- memset (&dtp.u.p, 0, sizeof (dtp.u.p));
- dtp.u.p.current_unit = u;
- next_record (&dtp, 1);
- }
-
- unit_truncate (u, stell (u->s), &fpp->common);
- u->endfile = AFTER_ENDFILE;
- if (0 == stell (u->s))
- u->flags.position = POSITION_REWIND;
- }
- else
- {
- if (fpp->common.unit < 0)
- {
- generate_error (&fpp->common, LIBERROR_BAD_OPTION,
- "Bad unit number in statement");
- return;
- }
-
- u = find_or_create_unit (fpp->common.unit);
- if (u->s == NULL)
- {
- /* Open the unit with some default flags. */
- st_parameter_open opp;
- unit_flags u_flags;
-
- memset (&u_flags, '\0', sizeof (u_flags));
- u_flags.access = ACCESS_SEQUENTIAL;
- u_flags.action = ACTION_READWRITE;
-
- /* Is it unformatted? */
- if (!(fpp->common.flags & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT
- | IOPARM_DT_IONML_SET)))
- u_flags.form = FORM_UNFORMATTED;
- else
- u_flags.form = FORM_UNSPECIFIED;
-
- u_flags.delim = DELIM_UNSPECIFIED;
- u_flags.blank = BLANK_UNSPECIFIED;
- u_flags.pad = PAD_UNSPECIFIED;
- u_flags.decimal = DECIMAL_UNSPECIFIED;
- u_flags.encoding = ENCODING_UNSPECIFIED;
- u_flags.async = ASYNC_UNSPECIFIED;
- u_flags.round = ROUND_UNSPECIFIED;
- u_flags.sign = SIGN_UNSPECIFIED;
- u_flags.status = STATUS_UNKNOWN;
- u_flags.convert = GFC_CONVERT_NATIVE;
-
- opp.common = fpp->common;
- opp.common.flags &= IOPARM_COMMON_MASK;
- u = new_unit (&opp, u, &u_flags);
- if (u == NULL)
- return;
- u->endfile = AFTER_ENDFILE;
- }
- }
-
- done:
- unlock_unit (u);
-
- library_end ();
-}
-
-
-extern void st_rewind (st_parameter_filepos *);
-export_proto(st_rewind);
-
-void
-st_rewind (st_parameter_filepos *fpp)
-{
- gfc_unit *u;
-
- library_start (&fpp->common);
-
- u = find_unit (fpp->common.unit);
- if (u != NULL)
- {
- if (u->flags.access == ACCESS_DIRECT)
- generate_error (&fpp->common, LIBERROR_BAD_OPTION,
- "Cannot REWIND a file opened for DIRECT access");
- else
- {
- /* If there are previously written bytes from a write with ADVANCE="no",
- add a record marker before performing the ENDFILE. */
-
- if (u->previous_nonadvancing_write)
- finish_last_advance_record (u);
-
- u->previous_nonadvancing_write = 0;
-
- fbuf_reset (u);
-
- u->last_record = 0;
-
- if (sseek (u->s, 0, SEEK_SET) < 0)
- generate_error (&fpp->common, LIBERROR_OS, NULL);
-
- /* Set this for compatibilty with g77 for /dev/null. */
- if (ssize (u->s) == 0)
- u->endfile = AT_ENDFILE;
- else
- {
- /* We are rewinding so we are not at the end. */
- u->endfile = NO_ENDFILE;
- }
-
- u->current_record = 0;
- u->strm_pos = 1;
- u->read_bad = 0;
- }
- /* Update position for INQUIRE. */
- u->flags.position = POSITION_REWIND;
- unlock_unit (u);
- }
-
- library_end ();
-}
-
-
-extern void st_flush (st_parameter_filepos *);
-export_proto(st_flush);
-
-void
-st_flush (st_parameter_filepos *fpp)
-{
- gfc_unit *u;
-
- library_start (&fpp->common);
-
- u = find_unit (fpp->common.unit);
- if (u != NULL)
- {
- /* Make sure format buffer is flushed. */
- if (u->flags.form == FORM_FORMATTED)
- fbuf_flush (u, u->mode);
-
- sflush (u->s);
- unlock_unit (u);
- }
- else
- /* FLUSH on unconnected unit is illegal: F95 std., 9.3.5. */
- generate_error (&fpp->common, LIBERROR_BAD_OPTION,
- "Specified UNIT in FLUSH is not connected");
-
- library_end ();
-}
diff --git a/gcc-4.8.1/libgfortran/io/format.c b/gcc-4.8.1/libgfortran/io/format.c
deleted file mode 100644
index 3c685e34e..000000000
--- a/gcc-4.8.1/libgfortran/io/format.c
+++ /dev/null
@@ -1,1401 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-
-/* format.c-- parse a FORMAT string into a binary format suitable for
- * interpretation during I/O statements */
-
-#include "io.h"
-#include "format.h"
-#include <ctype.h>
-#include <string.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-
-static const fnode colon_node = { FMT_COLON, 0, NULL, NULL, {{ 0, 0, 0 }}, 0,
- NULL };
-
-/* Error messages. */
-
-static const char posint_required[] = "Positive width required in format",
- period_required[] = "Period required in format",
- nonneg_required[] = "Nonnegative width required in format",
- unexpected_element[] = "Unexpected element '%c' in format\n",
- unexpected_end[] = "Unexpected end of format string",
- bad_string[] = "Unterminated character constant in format",
- bad_hollerith[] = "Hollerith constant extends past the end of the format",
- reversion_error[] = "Exhausted data descriptors in format",
- zero_width[] = "Zero width in format descriptor";
-
-/* The following routines support caching format data from parsed format strings
- into a hash table. This avoids repeatedly parsing duplicate format strings
- or format strings in I/O statements that are repeated in loops. */
-
-
-/* Traverse the table and free all data. */
-
-void
-free_format_hash_table (gfc_unit *u)
-{
- size_t i;
-
- /* free_format_data handles any NULL pointers. */
- for (i = 0; i < FORMAT_HASH_SIZE; i++)
- {
- if (u->format_hash_table[i].hashed_fmt != NULL)
- {
- free_format_data (u->format_hash_table[i].hashed_fmt);
- free (u->format_hash_table[i].key);
- }
- u->format_hash_table[i].key = NULL;
- u->format_hash_table[i].key_len = 0;
- u->format_hash_table[i].hashed_fmt = NULL;
- }
-}
-
-/* Traverse the format_data structure and reset the fnode counters. */
-
-static void
-reset_node (fnode *fn)
-{
- fnode *f;
-
- fn->count = 0;
- fn->current = NULL;
-
- if (fn->format != FMT_LPAREN)
- return;
-
- for (f = fn->u.child; f; f = f->next)
- {
- if (f->format == FMT_RPAREN)
- break;
- reset_node (f);
- }
-}
-
-static void
-reset_fnode_counters (st_parameter_dt *dtp)
-{
- fnode *f;
- format_data *fmt;
-
- fmt = dtp->u.p.fmt;
-
- /* Clear this pointer at the head so things start at the right place. */
- fmt->array.array[0].current = NULL;
-
- for (f = fmt->array.array[0].u.child; f; f = f->next)
- reset_node (f);
-}
-
-
-/* A simple hashing function to generate an index into the hash table. */
-
-static uint32_t
-format_hash (st_parameter_dt *dtp)
-{
- char *key;
- gfc_charlen_type key_len;
- uint32_t hash = 0;
- gfc_charlen_type i;
-
- /* Hash the format string. Super simple, but what the heck! */
- key = dtp->format;
- key_len = dtp->format_len;
- for (i = 0; i < key_len; i++)
- hash ^= key[i];
- hash &= (FORMAT_HASH_SIZE - 1);
- return hash;
-}
-
-
-static void
-save_parsed_format (st_parameter_dt *dtp)
-{
- uint32_t hash;
- gfc_unit *u;
-
- hash = format_hash (dtp);
- u = dtp->u.p.current_unit;
-
- /* Index into the hash table. We are simply replacing whatever is there
- relying on probability. */
- if (u->format_hash_table[hash].hashed_fmt != NULL)
- free_format_data (u->format_hash_table[hash].hashed_fmt);
- u->format_hash_table[hash].hashed_fmt = NULL;
-
- free (u->format_hash_table[hash].key);
- u->format_hash_table[hash].key = dtp->format;
-
- u->format_hash_table[hash].key_len = dtp->format_len;
- u->format_hash_table[hash].hashed_fmt = dtp->u.p.fmt;
-}
-
-
-static format_data *
-find_parsed_format (st_parameter_dt *dtp)
-{
- uint32_t hash;
- gfc_unit *u;
-
- hash = format_hash (dtp);
- u = dtp->u.p.current_unit;
-
- if (u->format_hash_table[hash].key != NULL)
- {
- /* See if it matches. */
- if (u->format_hash_table[hash].key_len == dtp->format_len)
- {
- /* So far so good. */
- if (strncmp (u->format_hash_table[hash].key,
- dtp->format, dtp->format_len) == 0)
- return u->format_hash_table[hash].hashed_fmt;
- }
- }
- return NULL;
-}
-
-
-/* next_char()-- Return the next character in the format string.
- * Returns -1 when the string is done. If the literal flag is set,
- * spaces are significant, otherwise they are not. */
-
-static int
-next_char (format_data *fmt, int literal)
-{
- int c;
-
- do
- {
- if (fmt->format_string_len == 0)
- return -1;
-
- fmt->format_string_len--;
- c = toupper (*fmt->format_string++);
- fmt->error_element = c;
- }
- while ((c == ' ' || c == '\t') && !literal);
-
- return c;
-}
-
-
-/* unget_char()-- Back up one character position. */
-
-#define unget_char(fmt) \
- { fmt->format_string--; fmt->format_string_len++; }
-
-
-/* get_fnode()-- Allocate a new format node, inserting it into the
- * current singly linked list. These are initially allocated from the
- * static buffer. */
-
-static fnode *
-get_fnode (format_data *fmt, fnode **head, fnode **tail, format_token t)
-{
- fnode *f;
-
- if (fmt->avail == &fmt->last->array[FARRAY_SIZE])
- {
- fmt->last->next = xmalloc (sizeof (fnode_array));
- fmt->last = fmt->last->next;
- fmt->last->next = NULL;
- fmt->avail = &fmt->last->array[0];
- }
- f = fmt->avail++;
- memset (f, '\0', sizeof (fnode));
-
- if (*head == NULL)
- *head = *tail = f;
- else
- {
- (*tail)->next = f;
- *tail = f;
- }
-
- f->format = t;
- f->repeat = -1;
- f->source = fmt->format_string;
- return f;
-}
-
-
-/* free_format_data()-- Free all allocated format data. */
-
-void
-free_format_data (format_data *fmt)
-{
- fnode_array *fa, *fa_next;
-
-
- if (fmt == NULL)
- return;
-
- for (fa = fmt->array.next; fa; fa = fa_next)
- {
- fa_next = fa->next;
- free (fa);
- }
-
- free (fmt);
- fmt = NULL;
-}
-
-
-/* format_lex()-- Simple lexical analyzer for getting the next token
- * in a FORMAT string. We support a one-level token pushback in the
- * fmt->saved_token variable. */
-
-static format_token
-format_lex (format_data *fmt)
-{
- format_token token;
- int negative_flag;
- int c;
- char delim;
-
- if (fmt->saved_token != FMT_NONE)
- {
- token = fmt->saved_token;
- fmt->saved_token = FMT_NONE;
- return token;
- }
-
- negative_flag = 0;
- c = next_char (fmt, 0);
-
- switch (c)
- {
- case '*':
- token = FMT_STAR;
- break;
-
- case '(':
- token = FMT_LPAREN;
- break;
-
- case ')':
- token = FMT_RPAREN;
- break;
-
- case '-':
- negative_flag = 1;
- /* Fall Through */
-
- case '+':
- c = next_char (fmt, 0);
- if (!isdigit (c))
- {
- token = FMT_UNKNOWN;
- break;
- }
-
- fmt->value = c - '0';
-
- for (;;)
- {
- c = next_char (fmt, 0);
- if (!isdigit (c))
- break;
-
- fmt->value = 10 * fmt->value + c - '0';
- }
-
- unget_char (fmt);
-
- if (negative_flag)
- fmt->value = -fmt->value;
- token = FMT_SIGNED_INT;
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- fmt->value = c - '0';
-
- for (;;)
- {
- c = next_char (fmt, 0);
- if (!isdigit (c))
- break;
-
- fmt->value = 10 * fmt->value + c - '0';
- }
-
- unget_char (fmt);
- token = (fmt->value == 0) ? FMT_ZERO : FMT_POSINT;
- break;
-
- case '.':
- token = FMT_PERIOD;
- break;
-
- case ',':
- token = FMT_COMMA;
- break;
-
- case ':':
- token = FMT_COLON;
- break;
-
- case '/':
- token = FMT_SLASH;
- break;
-
- case '$':
- token = FMT_DOLLAR;
- break;
-
- case 'T':
- switch (next_char (fmt, 0))
- {
- case 'L':
- token = FMT_TL;
- break;
- case 'R':
- token = FMT_TR;
- break;
- default:
- token = FMT_T;
- unget_char (fmt);
- break;
- }
-
- break;
-
- case 'X':
- token = FMT_X;
- break;
-
- case 'S':
- switch (next_char (fmt, 0))
- {
- case 'S':
- token = FMT_SS;
- break;
- case 'P':
- token = FMT_SP;
- break;
- default:
- token = FMT_S;
- unget_char (fmt);
- break;
- }
-
- break;
-
- case 'B':
- switch (next_char (fmt, 0))
- {
- case 'N':
- token = FMT_BN;
- break;
- case 'Z':
- token = FMT_BZ;
- break;
- default:
- token = FMT_B;
- unget_char (fmt);
- break;
- }
-
- break;
-
- case '\'':
- case '"':
- delim = c;
-
- fmt->string = fmt->format_string;
- fmt->value = 0; /* This is the length of the string */
-
- for (;;)
- {
- c = next_char (fmt, 1);
- if (c == -1)
- {
- token = FMT_BADSTRING;
- fmt->error = bad_string;
- break;
- }
-
- if (c == delim)
- {
- c = next_char (fmt, 1);
-
- if (c == -1)
- {
- token = FMT_BADSTRING;
- fmt->error = bad_string;
- break;
- }
-
- if (c != delim)
- {
- unget_char (fmt);
- token = FMT_STRING;
- break;
- }
- }
-
- fmt->value++;
- }
-
- break;
-
- case 'P':
- token = FMT_P;
- break;
-
- case 'I':
- token = FMT_I;
- break;
-
- case 'O':
- token = FMT_O;
- break;
-
- case 'Z':
- token = FMT_Z;
- break;
-
- case 'F':
- token = FMT_F;
- break;
-
- case 'E':
- switch (next_char (fmt, 0))
- {
- case 'N':
- token = FMT_EN;
- break;
- case 'S':
- token = FMT_ES;
- break;
- default:
- token = FMT_E;
- unget_char (fmt);
- break;
- }
- break;
-
- case 'G':
- token = FMT_G;
- break;
-
- case 'H':
- token = FMT_H;
- break;
-
- case 'L':
- token = FMT_L;
- break;
-
- case 'A':
- token = FMT_A;
- break;
-
- case 'D':
- switch (next_char (fmt, 0))
- {
- case 'P':
- token = FMT_DP;
- break;
- case 'C':
- token = FMT_DC;
- break;
- default:
- token = FMT_D;
- unget_char (fmt);
- break;
- }
- break;
-
- case 'R':
- switch (next_char (fmt, 0))
- {
- case 'C':
- token = FMT_RC;
- break;
- case 'D':
- token = FMT_RD;
- break;
- case 'N':
- token = FMT_RN;
- break;
- case 'P':
- token = FMT_RP;
- break;
- case 'U':
- token = FMT_RU;
- break;
- case 'Z':
- token = FMT_RZ;
- break;
- default:
- unget_char (fmt);
- token = FMT_UNKNOWN;
- break;
- }
- break;
-
- case -1:
- token = FMT_END;
- break;
-
- default:
- token = FMT_UNKNOWN;
- break;
- }
-
- return token;
-}
-
-
-/* parse_format_list()-- Parse a format list. Assumes that a left
- * paren has already been seen. Returns a list representing the
- * parenthesis node which contains the rest of the list. */
-
-static fnode *
-parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
-{
- fnode *head, *tail;
- format_token t, u, t2;
- int repeat;
- format_data *fmt = dtp->u.p.fmt;
- bool seen_data_desc = false;
-
- head = tail = NULL;
-
- /* Get the next format item */
- format_item:
- t = format_lex (fmt);
- format_item_1:
- switch (t)
- {
- case FMT_STAR:
- t = format_lex (fmt);
- if (t != FMT_LPAREN)
- {
- fmt->error = "Left parenthesis required after '*'";
- goto finished;
- }
- get_fnode (fmt, &head, &tail, FMT_LPAREN);
- tail->repeat = -2; /* Signifies unlimited format. */
- tail->u.child = parse_format_list (dtp, &seen_data_desc);
- if (fmt->error != NULL)
- goto finished;
- if (!seen_data_desc)
- {
- fmt->error = "'*' requires at least one associated data descriptor";
- goto finished;
- }
- goto between_desc;
-
- case FMT_POSINT:
- repeat = fmt->value;
-
- t = format_lex (fmt);
- switch (t)
- {
- case FMT_LPAREN:
- get_fnode (fmt, &head, &tail, FMT_LPAREN);
- tail->repeat = repeat;
- tail->u.child = parse_format_list (dtp, &seen_data_desc);
- *seen_dd = seen_data_desc;
- if (fmt->error != NULL)
- goto finished;
-
- goto between_desc;
-
- case FMT_SLASH:
- get_fnode (fmt, &head, &tail, FMT_SLASH);
- tail->repeat = repeat;
- goto optional_comma;
-
- case FMT_X:
- get_fnode (fmt, &head, &tail, FMT_X);
- tail->repeat = 1;
- tail->u.k = fmt->value;
- goto between_desc;
-
- case FMT_P:
- goto p_descriptor;
-
- default:
- goto data_desc;
- }
-
- case FMT_LPAREN:
- get_fnode (fmt, &head, &tail, FMT_LPAREN);
- tail->repeat = 1;
- tail->u.child = parse_format_list (dtp, &seen_data_desc);
- *seen_dd = seen_data_desc;
- if (fmt->error != NULL)
- goto finished;
-
- goto between_desc;
-
- case FMT_SIGNED_INT: /* Signed integer can only precede a P format. */
- case FMT_ZERO: /* Same for zero. */
- t = format_lex (fmt);
- if (t != FMT_P)
- {
- fmt->error = "Expected P edit descriptor in format";
- goto finished;
- }
-
- p_descriptor:
- get_fnode (fmt, &head, &tail, FMT_P);
- tail->u.k = fmt->value;
- tail->repeat = 1;
-
- t = format_lex (fmt);
- if (t == FMT_F || t == FMT_EN || t == FMT_ES || t == FMT_D
- || t == FMT_G || t == FMT_E)
- {
- repeat = 1;
- goto data_desc;
- }
-
- if (t != FMT_COMMA && t != FMT_RPAREN && t != FMT_SLASH
- && t != FMT_POSINT)
- {
- fmt->error = "Comma required after P descriptor";
- goto finished;
- }
-
- fmt->saved_token = t;
- goto optional_comma;
-
- case FMT_P: /* P and X require a prior number */
- fmt->error = "P descriptor requires leading scale factor";
- goto finished;
-
- case FMT_X:
-/*
- EXTENSION!
-
- If we would be pedantic in the library, we would have to reject
- an X descriptor without an integer prefix:
-
- fmt->error = "X descriptor requires leading space count";
- goto finished;
-
- However, this is an extension supported by many Fortran compilers,
- including Cray, HP, AIX, and IRIX. Therefore, we allow it in the
- runtime library, and make the front end reject it if the compiler
- is in pedantic mode. The interpretation of 'X' is '1X'.
-*/
- get_fnode (fmt, &head, &tail, FMT_X);
- tail->repeat = 1;
- tail->u.k = 1;
- goto between_desc;
-
- case FMT_STRING:
- get_fnode (fmt, &head, &tail, FMT_STRING);
- tail->u.string.p = fmt->string;
- tail->u.string.length = fmt->value;
- tail->repeat = 1;
- goto optional_comma;
-
- case FMT_RC:
- case FMT_RD:
- case FMT_RN:
- case FMT_RP:
- case FMT_RU:
- case FMT_RZ:
- notify_std (&dtp->common, GFC_STD_F2003, "Fortran 2003: Round "
- "descriptor not allowed");
- get_fnode (fmt, &head, &tail, t);
- tail->repeat = 1;
- goto between_desc;
-
- case FMT_DC:
- case FMT_DP:
- notify_std (&dtp->common, GFC_STD_F2003, "Fortran 2003: DC or DP "
- "descriptor not allowed");
- /* Fall through. */
- case FMT_S:
- case FMT_SS:
- case FMT_SP:
- case FMT_BN:
- case FMT_BZ:
- get_fnode (fmt, &head, &tail, t);
- tail->repeat = 1;
- goto between_desc;
-
- case FMT_COLON:
- get_fnode (fmt, &head, &tail, FMT_COLON);
- tail->repeat = 1;
- goto optional_comma;
-
- case FMT_SLASH:
- get_fnode (fmt, &head, &tail, FMT_SLASH);
- tail->repeat = 1;
- tail->u.r = 1;
- goto optional_comma;
-
- case FMT_DOLLAR:
- get_fnode (fmt, &head, &tail, FMT_DOLLAR);
- tail->repeat = 1;
- notify_std (&dtp->common, GFC_STD_GNU, "Extension: $ descriptor");
- goto between_desc;
-
- case FMT_T:
- case FMT_TL:
- case FMT_TR:
- t2 = format_lex (fmt);
- if (t2 != FMT_POSINT)
- {
- fmt->error = posint_required;
- goto finished;
- }
- get_fnode (fmt, &head, &tail, t);
- tail->u.n = fmt->value;
- tail->repeat = 1;
- goto between_desc;
-
- case FMT_I:
- case FMT_B:
- case FMT_O:
- case FMT_Z:
- case FMT_E:
- case FMT_EN:
- case FMT_ES:
- case FMT_D:
- case FMT_L:
- case FMT_A:
- case FMT_F:
- case FMT_G:
- repeat = 1;
- *seen_dd = true;
- goto data_desc;
-
- case FMT_H:
- get_fnode (fmt, &head, &tail, FMT_STRING);
- if (fmt->format_string_len < 1)
- {
- fmt->error = bad_hollerith;
- goto finished;
- }
-
- tail->u.string.p = fmt->format_string;
- tail->u.string.length = 1;
- tail->repeat = 1;
-
- fmt->format_string++;
- fmt->format_string_len--;
-
- goto between_desc;
-
- case FMT_END:
- fmt->error = unexpected_end;
- goto finished;
-
- case FMT_BADSTRING:
- goto finished;
-
- case FMT_RPAREN:
- goto finished;
-
- default:
- fmt->error = unexpected_element;
- goto finished;
- }
-
- /* In this state, t must currently be a data descriptor. Deal with
- things that can/must follow the descriptor */
- data_desc:
- switch (t)
- {
- case FMT_L:
- t = format_lex (fmt);
- if (t != FMT_POSINT)
- {
- if (notification_std(GFC_STD_GNU) == NOTIFICATION_ERROR)
- {
- fmt->error = posint_required;
- goto finished;
- }
- else
- {
- fmt->saved_token = t;
- fmt->value = 1; /* Default width */
- notify_std (&dtp->common, GFC_STD_GNU, posint_required);
- }
- }
-
- get_fnode (fmt, &head, &tail, FMT_L);
- tail->u.n = fmt->value;
- tail->repeat = repeat;
- break;
-
- case FMT_A:
- t = format_lex (fmt);
- if (t == FMT_ZERO)
- {
- fmt->error = zero_width;
- goto finished;
- }
-
- if (t != FMT_POSINT)
- {
- fmt->saved_token = t;
- fmt->value = -1; /* Width not present */
- }
-
- get_fnode (fmt, &head, &tail, FMT_A);
- tail->repeat = repeat;
- tail->u.n = fmt->value;
- break;
-
- case FMT_D:
- case FMT_E:
- case FMT_F:
- case FMT_G:
- case FMT_EN:
- case FMT_ES:
- get_fnode (fmt, &head, &tail, t);
- tail->repeat = repeat;
-
- u = format_lex (fmt);
- if (t == FMT_G && u == FMT_ZERO)
- {
- if (notification_std (GFC_STD_F2008) == NOTIFICATION_ERROR
- || dtp->u.p.mode == READING)
- {
- fmt->error = zero_width;
- goto finished;
- }
- tail->u.real.w = 0;
- u = format_lex (fmt);
- if (u != FMT_PERIOD)
- {
- fmt->saved_token = u;
- break;
- }
-
- u = format_lex (fmt);
- if (u != FMT_POSINT)
- {
- fmt->error = posint_required;
- goto finished;
- }
- tail->u.real.d = fmt->value;
- break;
- }
- if (t == FMT_F && dtp->u.p.mode == WRITING)
- {
- if (u != FMT_POSINT && u != FMT_ZERO)
- {
- fmt->error = nonneg_required;
- goto finished;
- }
- }
- else if (u != FMT_POSINT)
- {
- fmt->error = posint_required;
- goto finished;
- }
-
- tail->u.real.w = fmt->value;
- t2 = t;
- t = format_lex (fmt);
- if (t != FMT_PERIOD)
- {
- /* We treat a missing decimal descriptor as 0. Note: This is only
- allowed if -std=legacy, otherwise an error occurs. */
- if (compile_options.warn_std != 0)
- {
- fmt->error = period_required;
- goto finished;
- }
- fmt->saved_token = t;
- tail->u.real.d = 0;
- tail->u.real.e = -1;
- break;
- }
-
- t = format_lex (fmt);
- if (t != FMT_ZERO && t != FMT_POSINT)
- {
- fmt->error = nonneg_required;
- goto finished;
- }
-
- tail->u.real.d = fmt->value;
- tail->u.real.e = -1;
-
- if (t2 == FMT_D || t2 == FMT_F)
- break;
-
-
- /* Look for optional exponent */
- t = format_lex (fmt);
- if (t != FMT_E)
- fmt->saved_token = t;
- else
- {
- t = format_lex (fmt);
- if (t != FMT_POSINT)
- {
- fmt->error = "Positive exponent width required in format";
- goto finished;
- }
-
- tail->u.real.e = fmt->value;
- }
-
- break;
-
- case FMT_H:
- if (repeat > fmt->format_string_len)
- {
- fmt->error = bad_hollerith;
- goto finished;
- }
-
- get_fnode (fmt, &head, &tail, FMT_STRING);
- tail->u.string.p = fmt->format_string;
- tail->u.string.length = repeat;
- tail->repeat = 1;
-
- fmt->format_string += fmt->value;
- fmt->format_string_len -= repeat;
-
- break;
-
- case FMT_I:
- case FMT_B:
- case FMT_O:
- case FMT_Z:
- get_fnode (fmt, &head, &tail, t);
- tail->repeat = repeat;
-
- t = format_lex (fmt);
-
- if (dtp->u.p.mode == READING)
- {
- if (t != FMT_POSINT)
- {
- fmt->error = posint_required;
- goto finished;
- }
- }
- else
- {
- if (t != FMT_ZERO && t != FMT_POSINT)
- {
- fmt->error = nonneg_required;
- goto finished;
- }
- }
-
- tail->u.integer.w = fmt->value;
- tail->u.integer.m = -1;
-
- t = format_lex (fmt);
- if (t != FMT_PERIOD)
- {
- fmt->saved_token = t;
- }
- else
- {
- t = format_lex (fmt);
- if (t != FMT_ZERO && t != FMT_POSINT)
- {
- fmt->error = nonneg_required;
- goto finished;
- }
-
- tail->u.integer.m = fmt->value;
- }
-
- if (tail->u.integer.w != 0 && tail->u.integer.m > tail->u.integer.w)
- {
- fmt->error = "Minimum digits exceeds field width";
- goto finished;
- }
-
- break;
-
- default:
- fmt->error = unexpected_element;
- goto finished;
- }
-
- /* Between a descriptor and what comes next */
- between_desc:
- t = format_lex (fmt);
- switch (t)
- {
- case FMT_COMMA:
- goto format_item;
-
- case FMT_RPAREN:
- goto finished;
-
- case FMT_SLASH:
- case FMT_COLON:
- get_fnode (fmt, &head, &tail, t);
- tail->repeat = 1;
- goto optional_comma;
-
- case FMT_END:
- fmt->error = unexpected_end;
- goto finished;
-
- default:
- /* Assume a missing comma, this is a GNU extension */
- goto format_item_1;
- }
-
- /* Optional comma is a weird between state where we've just finished
- reading a colon, slash or P descriptor. */
- optional_comma:
- t = format_lex (fmt);
- switch (t)
- {
- case FMT_COMMA:
- break;
-
- case FMT_RPAREN:
- goto finished;
-
- default: /* Assume that we have another format item */
- fmt->saved_token = t;
- break;
- }
-
- goto format_item;
-
- finished:
-
- return head;
-}
-
-
-/* format_error()-- Generate an error message for a format statement.
- * If the node that gives the location of the error is NULL, the error
- * is assumed to happen at parse time, and the current location of the
- * parser is shown.
- *
- * We generate a message showing where the problem is. We take extra
- * care to print only the relevant part of the format if it is longer
- * than a standard 80 column display. */
-
-void
-format_error (st_parameter_dt *dtp, const fnode *f, const char *message)
-{
- int width, i, j, offset;
-#define BUFLEN 300
- char *p, buffer[BUFLEN];
- format_data *fmt = dtp->u.p.fmt;
-
- if (f != NULL)
- fmt->format_string = f->source;
-
- if (message == unexpected_element)
- snprintf (buffer, BUFLEN, message, fmt->error_element);
- else
- snprintf (buffer, BUFLEN, "%s\n", message);
-
- j = fmt->format_string - dtp->format;
-
- offset = (j > 60) ? j - 40 : 0;
-
- j -= offset;
- width = dtp->format_len - offset;
-
- if (width > 80)
- width = 80;
-
- /* Show the format */
-
- p = strchr (buffer, '\0');
-
- memcpy (p, dtp->format + offset, width);
-
- p += width;
- *p++ = '\n';
-
- /* Show where the problem is */
-
- for (i = 1; i < j; i++)
- *p++ = ' ';
-
- *p++ = '^';
- *p = '\0';
-
- generate_error (&dtp->common, LIBERROR_FORMAT, buffer);
-}
-
-
-/* revert()-- Do reversion of the format. Control reverts to the left
- * parenthesis that matches the rightmost right parenthesis. From our
- * tree structure, we are looking for the rightmost parenthesis node
- * at the second level, the first level always being a single
- * parenthesis node. If this node doesn't exit, we use the top
- * level. */
-
-static void
-revert (st_parameter_dt *dtp)
-{
- fnode *f, *r;
- format_data *fmt = dtp->u.p.fmt;
-
- dtp->u.p.reversion_flag = 1;
-
- r = NULL;
-
- for (f = fmt->array.array[0].u.child; f; f = f->next)
- if (f->format == FMT_LPAREN)
- r = f;
-
- /* If r is NULL because no node was found, the whole tree will be used */
-
- fmt->array.array[0].current = r;
- fmt->array.array[0].count = 0;
-}
-
-/* parse_format()-- Parse a format string. */
-
-void
-parse_format (st_parameter_dt *dtp)
-{
- format_data *fmt;
- bool format_cache_ok, seen_data_desc = false;
-
- /* Don't cache for internal units and set an arbitrary limit on the size of
- format strings we will cache. (Avoids memory issues.) */
- format_cache_ok = !is_internal_unit (dtp);
-
- /* Lookup format string to see if it has already been parsed. */
- if (format_cache_ok)
- {
- dtp->u.p.fmt = find_parsed_format (dtp);
-
- if (dtp->u.p.fmt != NULL)
- {
- dtp->u.p.fmt->reversion_ok = 0;
- dtp->u.p.fmt->saved_token = FMT_NONE;
- dtp->u.p.fmt->saved_format = NULL;
- reset_fnode_counters (dtp);
- return;
- }
- }
-
- /* Not found so proceed as follows. */
-
- if (format_cache_ok)
- {
- char *fmt_string = xmalloc (dtp->format_len);
- memcpy (fmt_string, dtp->format, dtp->format_len);
- dtp->format = fmt_string;
- }
-
- dtp->u.p.fmt = fmt = xmalloc (sizeof (format_data));
- fmt->format_string = dtp->format;
- fmt->format_string_len = dtp->format_len;
-
- fmt->string = NULL;
- fmt->saved_token = FMT_NONE;
- fmt->error = NULL;
- fmt->value = 0;
-
- /* Initialize variables used during traversal of the tree. */
-
- fmt->reversion_ok = 0;
- fmt->saved_format = NULL;
-
- /* Allocate the first format node as the root of the tree. */
-
- fmt->last = &fmt->array;
- fmt->last->next = NULL;
- fmt->avail = &fmt->array.array[0];
-
- memset (fmt->avail, 0, sizeof (*fmt->avail));
- fmt->avail->format = FMT_LPAREN;
- fmt->avail->repeat = 1;
- fmt->avail++;
-
- if (format_lex (fmt) == FMT_LPAREN)
- fmt->array.array[0].u.child = parse_format_list (dtp, &seen_data_desc);
- else
- fmt->error = "Missing initial left parenthesis in format";
-
- if (fmt->error)
- {
- format_error (dtp, NULL, fmt->error);
- if (format_cache_ok)
- free (dtp->format);
- free_format_hash_table (dtp->u.p.current_unit);
- return;
- }
-
- if (format_cache_ok)
- save_parsed_format (dtp);
- else
- dtp->u.p.format_not_saved = 1;
-}
-
-
-/* next_format0()-- Get the next format node without worrying about
- * reversion. Returns NULL when we hit the end of the list.
- * Parenthesis nodes are incremented after the list has been
- * exhausted, other nodes are incremented before they are returned. */
-
-static const fnode *
-next_format0 (fnode * f)
-{
- const fnode *r;
-
- if (f == NULL)
- return NULL;
-
- if (f->format != FMT_LPAREN)
- {
- f->count++;
- if (f->count <= f->repeat)
- return f;
-
- f->count = 0;
- return NULL;
- }
-
- /* Deal with a parenthesis node with unlimited format. */
-
- if (f->repeat == -2) /* -2 signifies unlimited. */
- for (;;)
- {
- if (f->current == NULL)
- f->current = f->u.child;
-
- for (; f->current != NULL; f->current = f->current->next)
- {
- r = next_format0 (f->current);
- if (r != NULL)
- return r;
- }
- }
-
- /* Deal with a parenthesis node with specific repeat count. */
- for (; f->count < f->repeat; f->count++)
- {
- if (f->current == NULL)
- f->current = f->u.child;
-
- for (; f->current != NULL; f->current = f->current->next)
- {
- r = next_format0 (f->current);
- if (r != NULL)
- return r;
- }
- }
-
- f->count = 0;
- return NULL;
-}
-
-
-/* next_format()-- Return the next format node. If the format list
- * ends up being exhausted, we do reversion. Reversion is only
- * allowed if we've seen a data descriptor since the
- * initialization or the last reversion. We return NULL if there
- * are no more data descriptors to return (which is an error
- * condition). */
-
-const fnode *
-next_format (st_parameter_dt *dtp)
-{
- format_token t;
- const fnode *f;
- format_data *fmt = dtp->u.p.fmt;
-
- if (fmt->saved_format != NULL)
- { /* Deal with a pushed-back format node */
- f = fmt->saved_format;
- fmt->saved_format = NULL;
- goto done;
- }
-
- f = next_format0 (&fmt->array.array[0]);
- if (f == NULL)
- {
- if (!fmt->reversion_ok)
- return NULL;
-
- fmt->reversion_ok = 0;
- revert (dtp);
-
- f = next_format0 (&fmt->array.array[0]);
- if (f == NULL)
- {
- format_error (dtp, NULL, reversion_error);
- return NULL;
- }
-
- /* Push the first reverted token and return a colon node in case
- * there are no more data items. */
-
- fmt->saved_format = f;
- return &colon_node;
- }
-
- /* If this is a data edit descriptor, then reversion has become OK. */
- done:
- t = f->format;
-
- if (!fmt->reversion_ok &&
- (t == FMT_I || t == FMT_B || t == FMT_O || t == FMT_Z || t == FMT_F ||
- t == FMT_E || t == FMT_EN || t == FMT_ES || t == FMT_G || t == FMT_L ||
- t == FMT_A || t == FMT_D))
- fmt->reversion_ok = 1;
- return f;
-}
-
-
-/* unget_format()-- Push the given format back so that it will be
- * returned on the next call to next_format() without affecting
- * counts. This is necessary when we've encountered a data
- * descriptor, but don't know what the data item is yet. The format
- * node is pushed back, and we return control to the main program,
- * which calls the library back with the data item (or not). */
-
-void
-unget_format (st_parameter_dt *dtp, const fnode *f)
-{
- dtp->u.p.fmt->saved_format = f;
-}
-
diff --git a/gcc-4.8.1/libgfortran/io/format.h b/gcc-4.8.1/libgfortran/io/format.h
deleted file mode 100644
index 529b93e98..000000000
--- a/gcc-4.8.1/libgfortran/io/format.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Copyright (C) 2009-2013 Free Software Foundation, Inc.
- Contributed by Janne Blomqvist
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef GFOR_FORMAT_H
-#define GFOR_FORMAT_H
-
-#include "io.h"
-
-
-/* Format tokens. Only about half of these can be stored in the
- format nodes. */
-
-typedef enum
-{
- FMT_NONE = 0, FMT_UNKNOWN, FMT_SIGNED_INT, FMT_ZERO, FMT_POSINT, FMT_PERIOD,
- FMT_COMMA, FMT_COLON, FMT_SLASH, FMT_DOLLAR, FMT_T, FMT_TR, FMT_TL,
- FMT_LPAREN, FMT_RPAREN, FMT_X, FMT_S, FMT_SS, FMT_SP, FMT_STRING,
- FMT_BADSTRING, FMT_P, FMT_I, FMT_B, FMT_BN, FMT_BZ, FMT_O, FMT_Z, FMT_F,
- FMT_E, FMT_EN, FMT_ES, FMT_G, FMT_L, FMT_A, FMT_D, FMT_H, FMT_END, FMT_DC,
- FMT_DP, FMT_STAR, FMT_RC, FMT_RD, FMT_RN, FMT_RP, FMT_RU, FMT_RZ
-}
-format_token;
-
-
-/* Format nodes. A format string is converted into a tree of these
- structures, which is traversed as part of a data transfer statement. */
-
-struct fnode
-{
- format_token format;
- int repeat;
- struct fnode *next;
- char *source;
-
- union
- {
- struct
- {
- int w, d, e;
- }
- real;
-
- struct
- {
- int length;
- char *p;
- }
- string;
-
- struct
- {
- int w, m;
- }
- integer;
-
- int w;
- int k;
- int r;
- int n;
-
- struct fnode *child;
- }
- u;
-
- /* Members for traversing the tree during data transfer. */
-
- int count;
- struct fnode *current;
-
-};
-
-
-/* A storage structures for format node data. */
-
-#define FARRAY_SIZE 64
-
-typedef struct fnode_array
-{
- struct fnode_array *next;
- fnode array[FARRAY_SIZE];
-}
-fnode_array;
-
-
-typedef struct format_data
-{
- char *format_string, *string;
- const char *error;
- char error_element;
- format_token saved_token;
- int value, format_string_len, reversion_ok;
- fnode *avail;
- const fnode *saved_format;
- fnode_array *last;
- fnode_array array;
-}
-format_data;
-
-extern void parse_format (st_parameter_dt *);
-internal_proto(parse_format);
-
-extern const fnode *next_format (st_parameter_dt *);
-internal_proto(next_format);
-
-extern void unget_format (st_parameter_dt *, const fnode *);
-internal_proto(unget_format);
-
-extern void format_error (st_parameter_dt *, const fnode *, const char *);
-internal_proto(format_error);
-
-extern void free_format_data (struct format_data *);
-internal_proto(free_format_data);
-
-extern void free_format_hash_table (gfc_unit *);
-internal_proto(free_format_hash_table);
-
-extern void init_format_hash (st_parameter_dt *);
-internal_proto(init_format_hash);
-
-extern void free_format_hash (st_parameter_dt *);
-internal_proto(free_format_hash);
-
-#endif
diff --git a/gcc-4.8.1/libgfortran/io/inquire.c b/gcc-4.8.1/libgfortran/io/inquire.c
deleted file mode 100644
index d91982a65..000000000
--- a/gcc-4.8.1/libgfortran/io/inquire.c
+++ /dev/null
@@ -1,743 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-
-/* Implement the non-IOLENGTH variant of the INQUIRY statement */
-
-#include "io.h"
-#include "unix.h"
-#include <string.h>
-
-
-static const char undefined[] = "UNDEFINED";
-
-
-/* inquire_via_unit()-- Inquiry via unit number. The unit might not exist. */
-
-static void
-inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
-{
- const char *p;
- GFC_INTEGER_4 cf = iqp->common.flags;
-
- if ((cf & IOPARM_INQUIRE_HAS_EXIST) != 0)
- {
- *iqp->exist = (iqp->common.unit >= 0
- && iqp->common.unit <= GFC_INTEGER_4_HUGE);
-
- if ((cf & IOPARM_INQUIRE_HAS_FILE) == 0)
- {
- if (!(*iqp->exist))
- *iqp->common.iostat = LIBERROR_BAD_UNIT;
- *iqp->exist = *iqp->exist
- && (*iqp->common.iostat != LIBERROR_BAD_UNIT);
- }
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_OPENED) != 0)
- *iqp->opened = (u != NULL);
-
- if ((cf & IOPARM_INQUIRE_HAS_NUMBER) != 0)
- *iqp->number = (u != NULL) ? u->unit_number : -1;
-
- if ((cf & IOPARM_INQUIRE_HAS_NAMED) != 0)
- *iqp->named = (u != NULL && u->flags.status != STATUS_SCRATCH);
-
- if ((cf & IOPARM_INQUIRE_HAS_NAME) != 0
- && u != NULL && u->flags.status != STATUS_SCRATCH)
- {
-#if defined(HAVE_TTYNAME_R) || defined(HAVE_TTYNAME)
- if (u->unit_number == options.stdin_unit
- || u->unit_number == options.stdout_unit
- || u->unit_number == options.stderr_unit)
- {
- int err = stream_ttyname (u->s, iqp->name, iqp->name_len);
- if (err == 0)
- {
- gfc_charlen_type tmplen = strlen (iqp->name);
- if (iqp->name_len > tmplen)
- memset (&iqp->name[tmplen], ' ', iqp->name_len - tmplen);
- }
- else /* If ttyname does not work, go with the default. */
- fstrcpy (iqp->name, iqp->name_len, u->file, u->file_len);
- }
- else
- fstrcpy (iqp->name, iqp->name_len, u->file, u->file_len);
-#elif defined __MINGW32__
- if (u->unit_number == options.stdin_unit)
- fstrcpy (iqp->name, iqp->name_len, "CONIN$", sizeof("CONIN$"));
- else if (u->unit_number == options.stdout_unit)
- fstrcpy (iqp->name, iqp->name_len, "CONOUT$", sizeof("CONOUT$"));
- else if (u->unit_number == options.stderr_unit)
- fstrcpy (iqp->name, iqp->name_len, "CONERR$", sizeof("CONERR$"));
- else
- fstrcpy (iqp->name, iqp->name_len, u->file, u->file_len);
-#else
- fstrcpy (iqp->name, iqp->name_len, u->file, u->file_len);
-#endif
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_ACCESS) != 0)
- {
- if (u == NULL)
- p = undefined;
- else
- switch (u->flags.access)
- {
- case ACCESS_SEQUENTIAL:
- p = "SEQUENTIAL";
- break;
- case ACCESS_DIRECT:
- p = "DIRECT";
- break;
- case ACCESS_STREAM:
- p = "STREAM";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad access");
- }
-
- cf_strcpy (iqp->access, iqp->access_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_SEQUENTIAL) != 0)
- {
- if (u == NULL)
- p = inquire_sequential (NULL, 0);
- else
- switch (u->flags.access)
- {
- case ACCESS_DIRECT:
- case ACCESS_STREAM:
- p = "NO";
- break;
- case ACCESS_SEQUENTIAL:
- p = "YES";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad access");
- }
-
- cf_strcpy (iqp->sequential, iqp->sequential_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_DIRECT) != 0)
- {
- if (u == NULL)
- p = inquire_direct (NULL, 0);
- else
- switch (u->flags.access)
- {
- case ACCESS_SEQUENTIAL:
- case ACCESS_STREAM:
- p = "NO";
- break;
- case ACCESS_DIRECT:
- p = "YES";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad access");
- }
-
- cf_strcpy (iqp->direct, iqp->direct_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_FORM) != 0)
- {
- if (u == NULL)
- p = undefined;
- else
- switch (u->flags.form)
- {
- case FORM_FORMATTED:
- p = "FORMATTED";
- break;
- case FORM_UNFORMATTED:
- p = "UNFORMATTED";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad form");
- }
-
- cf_strcpy (iqp->form, iqp->form_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_FORMATTED) != 0)
- {
- if (u == NULL)
- p = inquire_formatted (NULL, 0);
- else
- switch (u->flags.form)
- {
- case FORM_FORMATTED:
- p = "YES";
- break;
- case FORM_UNFORMATTED:
- p = "NO";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad form");
- }
-
- cf_strcpy (iqp->formatted, iqp->formatted_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_UNFORMATTED) != 0)
- {
- if (u == NULL)
- p = inquire_unformatted (NULL, 0);
- else
- switch (u->flags.form)
- {
- case FORM_FORMATTED:
- p = "NO";
- break;
- case FORM_UNFORMATTED:
- p = "YES";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad form");
- }
-
- cf_strcpy (iqp->unformatted, iqp->unformatted_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_RECL_OUT) != 0)
- *iqp->recl_out = (u != NULL) ? u->recl : 0;
-
- if ((cf & IOPARM_INQUIRE_HAS_STRM_POS_OUT) != 0)
- *iqp->strm_pos_out = (u != NULL) ? u->strm_pos : 0;
-
- if ((cf & IOPARM_INQUIRE_HAS_NEXTREC) != 0)
- {
- /* This only makes sense in the context of DIRECT access. */
- if (u != NULL && u->flags.access == ACCESS_DIRECT)
- *iqp->nextrec = u->last_record + 1;
- else
- *iqp->nextrec = 0;
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_BLANK) != 0)
- {
- if (u == NULL || u->flags.form != FORM_FORMATTED)
- p = undefined;
- else
- switch (u->flags.blank)
- {
- case BLANK_NULL:
- p = "NULL";
- break;
- case BLANK_ZERO:
- p = "ZERO";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad blank");
- }
-
- cf_strcpy (iqp->blank, iqp->blank_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_PAD) != 0)
- {
- if (u == NULL || u->flags.form != FORM_FORMATTED)
- p = undefined;
- else
- switch (u->flags.pad)
- {
- case PAD_YES:
- p = "YES";
- break;
- case PAD_NO:
- p = "NO";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
- }
-
- cf_strcpy (iqp->pad, iqp->pad_len, p);
- }
-
- if (cf & IOPARM_INQUIRE_HAS_FLAGS2)
- {
- GFC_INTEGER_4 cf2 = iqp->flags2;
-
- if ((cf2 & IOPARM_INQUIRE_HAS_PENDING) != 0)
- *iqp->pending = 0;
-
- if ((cf2 & IOPARM_INQUIRE_HAS_ID) != 0)
- *iqp->id = 0;
-
- if ((cf2 & IOPARM_INQUIRE_HAS_ENCODING) != 0)
- {
- if (u == NULL || u->flags.form != FORM_FORMATTED)
- p = undefined;
- else
- switch (u->flags.encoding)
- {
- case ENCODING_DEFAULT:
- p = "UNKNOWN";
- break;
- case ENCODING_UTF8:
- p = "UTF-8";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad encoding");
- }
-
- cf_strcpy (iqp->encoding, iqp->encoding_len, p);
- }
-
- if ((cf2 & IOPARM_INQUIRE_HAS_DECIMAL) != 0)
- {
- if (u == NULL || u->flags.form != FORM_FORMATTED)
- p = undefined;
- else
- switch (u->flags.decimal)
- {
- case DECIMAL_POINT:
- p = "POINT";
- break;
- case DECIMAL_COMMA:
- p = "COMMA";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad comma");
- }
-
- cf_strcpy (iqp->decimal, iqp->decimal_len, p);
- }
-
- if ((cf2 & IOPARM_INQUIRE_HAS_ASYNCHRONOUS) != 0)
- {
- if (u == NULL)
- p = undefined;
- else
- switch (u->flags.async)
- {
- case ASYNC_YES:
- p = "YES";
- break;
- case ASYNC_NO:
- p = "NO";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad async");
- }
-
- cf_strcpy (iqp->asynchronous, iqp->asynchronous_len, p);
- }
-
- if ((cf2 & IOPARM_INQUIRE_HAS_SIGN) != 0)
- {
- if (u == NULL)
- p = undefined;
- else
- switch (u->flags.sign)
- {
- case SIGN_PROCDEFINED:
- p = "PROCESSOR_DEFINED";
- break;
- case SIGN_SUPPRESS:
- p = "SUPPRESS";
- break;
- case SIGN_PLUS:
- p = "PLUS";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad sign");
- }
-
- cf_strcpy (iqp->sign, iqp->sign_len, p);
- }
-
- if ((cf2 & IOPARM_INQUIRE_HAS_ROUND) != 0)
- {
- if (u == NULL)
- p = undefined;
- else
- switch (u->flags.round)
- {
- case ROUND_UP:
- p = "UP";
- break;
- case ROUND_DOWN:
- p = "DOWN";
- break;
- case ROUND_ZERO:
- p = "ZERO";
- break;
- case ROUND_NEAREST:
- p = "NEAREST";
- break;
- case ROUND_COMPATIBLE:
- p = "COMPATIBLE";
- break;
- case ROUND_PROCDEFINED:
- p = "PROCESSOR_DEFINED";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad round");
- }
-
- cf_strcpy (iqp->round, iqp->round_len, p);
- }
-
- if ((cf2 & IOPARM_INQUIRE_HAS_SIZE) != 0)
- {
- if (u == NULL)
- *iqp->size = -1;
- else
- {
- sflush (u->s);
- *iqp->size = ssize (u->s);
- }
- }
-
- if ((cf2 & IOPARM_INQUIRE_HAS_IQSTREAM) != 0)
- {
- if (u == NULL)
- p = "UNKNOWN";
- else
- switch (u->flags.access)
- {
- case ACCESS_SEQUENTIAL:
- case ACCESS_DIRECT:
- p = "NO";
- break;
- case ACCESS_STREAM:
- p = "YES";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
- }
-
- cf_strcpy (iqp->iqstream, iqp->iqstream_len, p);
- }
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_POSITION) != 0)
- {
- if (u == NULL || u->flags.access == ACCESS_DIRECT)
- p = undefined;
- else
- {
- /* If the position is unspecified, check if we can figure
- out whether it's at the beginning or end. */
- if (u->flags.position == POSITION_UNSPECIFIED)
- {
- gfc_offset cur = stell (u->s);
- if (cur == 0)
- u->flags.position = POSITION_REWIND;
- else if (cur != -1 && (ssize (u->s) == cur))
- u->flags.position = POSITION_APPEND;
- }
- switch (u->flags.position)
- {
- case POSITION_REWIND:
- p = "REWIND";
- break;
- case POSITION_APPEND:
- p = "APPEND";
- break;
- case POSITION_ASIS:
- p = "ASIS";
- break;
- default:
- /* If the position has changed and is not rewind or
- append, it must be set to a processor-dependent
- value. */
- p = "UNSPECIFIED";
- break;
- }
- }
- cf_strcpy (iqp->position, iqp->position_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_ACTION) != 0)
- {
- if (u == NULL)
- p = undefined;
- else
- switch (u->flags.action)
- {
- case ACTION_READ:
- p = "READ";
- break;
- case ACTION_WRITE:
- p = "WRITE";
- break;
- case ACTION_READWRITE:
- p = "READWRITE";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad action");
- }
-
- cf_strcpy (iqp->action, iqp->action_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_READ) != 0)
- {
- p = (u == NULL) ? inquire_read (NULL, 0) :
- inquire_read (u->file, u->file_len);
-
- cf_strcpy (iqp->read, iqp->read_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_WRITE) != 0)
- {
- p = (u == NULL) ? inquire_write (NULL, 0) :
- inquire_write (u->file, u->file_len);
-
- cf_strcpy (iqp->write, iqp->write_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_READWRITE) != 0)
- {
- p = (u == NULL) ? inquire_readwrite (NULL, 0) :
- inquire_readwrite (u->file, u->file_len);
-
- cf_strcpy (iqp->readwrite, iqp->readwrite_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_DELIM) != 0)
- {
- if (u == NULL || u->flags.form != FORM_FORMATTED)
- p = undefined;
- else
- switch (u->flags.delim)
- {
- case DELIM_NONE:
- p = "NONE";
- break;
- case DELIM_QUOTE:
- p = "QUOTE";
- break;
- case DELIM_APOSTROPHE:
- p = "APOSTROPHE";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad delim");
- }
-
- cf_strcpy (iqp->delim, iqp->delim_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_PAD) != 0)
- {
- if (u == NULL || u->flags.form != FORM_FORMATTED)
- p = undefined;
- else
- switch (u->flags.pad)
- {
- case PAD_NO:
- p = "NO";
- break;
- case PAD_YES:
- p = "YES";
- break;
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
- }
-
- cf_strcpy (iqp->pad, iqp->pad_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_CONVERT) != 0)
- {
- if (u == NULL)
- p = undefined;
- else
- switch (u->flags.convert)
- {
- /* big_endian is 0 for little-endian, 1 for big-endian. */
- case GFC_CONVERT_NATIVE:
- p = big_endian ? "BIG_ENDIAN" : "LITTLE_ENDIAN";
- break;
-
- case GFC_CONVERT_SWAP:
- p = big_endian ? "LITTLE_ENDIAN" : "BIG_ENDIAN";
- break;
-
- default:
- internal_error (&iqp->common, "inquire_via_unit(): Bad convert");
- }
-
- cf_strcpy (iqp->convert, iqp->convert_len, p);
- }
-}
-
-
-/* inquire_via_filename()-- Inquiry via filename. This subroutine is
- * only used if the filename is *not* connected to a unit number. */
-
-static void
-inquire_via_filename (st_parameter_inquire *iqp)
-{
- const char *p;
- GFC_INTEGER_4 cf = iqp->common.flags;
-
- if ((cf & IOPARM_INQUIRE_HAS_EXIST) != 0)
- *iqp->exist = file_exists (iqp->file, iqp->file_len);
-
- if ((cf & IOPARM_INQUIRE_HAS_OPENED) != 0)
- *iqp->opened = 0;
-
- if ((cf & IOPARM_INQUIRE_HAS_NUMBER) != 0)
- *iqp->number = -1;
-
- if ((cf & IOPARM_INQUIRE_HAS_NAMED) != 0)
- *iqp->named = 1;
-
- if ((cf & IOPARM_INQUIRE_HAS_NAME) != 0)
- fstrcpy (iqp->name, iqp->name_len, iqp->file, iqp->file_len);
-
- if ((cf & IOPARM_INQUIRE_HAS_ACCESS) != 0)
- cf_strcpy (iqp->access, iqp->access_len, undefined);
-
- if ((cf & IOPARM_INQUIRE_HAS_SEQUENTIAL) != 0)
- {
- p = "UNKNOWN";
- cf_strcpy (iqp->sequential, iqp->sequential_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_DIRECT) != 0)
- {
- p = "UNKNOWN";
- cf_strcpy (iqp->direct, iqp->direct_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_FORM) != 0)
- cf_strcpy (iqp->form, iqp->form_len, undefined);
-
- if ((cf & IOPARM_INQUIRE_HAS_FORMATTED) != 0)
- {
- p = "UNKNOWN";
- cf_strcpy (iqp->formatted, iqp->formatted_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_UNFORMATTED) != 0)
- {
- p = "UNKNOWN";
- cf_strcpy (iqp->unformatted, iqp->unformatted_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_RECL_OUT) != 0)
- *iqp->recl_out = 0;
-
- if ((cf & IOPARM_INQUIRE_HAS_NEXTREC) != 0)
- *iqp->nextrec = 0;
-
- if ((cf & IOPARM_INQUIRE_HAS_BLANK) != 0)
- cf_strcpy (iqp->blank, iqp->blank_len, undefined);
-
- if ((cf & IOPARM_INQUIRE_HAS_PAD) != 0)
- cf_strcpy (iqp->pad, iqp->pad_len, undefined);
-
- if (cf & IOPARM_INQUIRE_HAS_FLAGS2)
- {
- GFC_INTEGER_4 cf2 = iqp->flags2;
-
- if ((cf2 & IOPARM_INQUIRE_HAS_ENCODING) != 0)
- cf_strcpy (iqp->encoding, iqp->encoding_len, undefined);
-
- if ((cf2 & IOPARM_INQUIRE_HAS_DELIM) != 0)
- cf_strcpy (iqp->delim, iqp->delim_len, undefined);
-
- if ((cf2 & IOPARM_INQUIRE_HAS_DECIMAL) != 0)
- cf_strcpy (iqp->decimal, iqp->decimal_len, undefined);
-
- if ((cf2 & IOPARM_INQUIRE_HAS_DELIM) != 0)
- cf_strcpy (iqp->delim, iqp->delim_len, undefined);
-
- if ((cf2 & IOPARM_INQUIRE_HAS_PAD) != 0)
- cf_strcpy (iqp->pad, iqp->pad_len, undefined);
-
- if ((cf2 & IOPARM_INQUIRE_HAS_ENCODING) != 0)
- cf_strcpy (iqp->encoding, iqp->encoding_len, undefined);
-
- if ((cf2 & IOPARM_INQUIRE_HAS_SIZE) != 0)
- *iqp->size = file_size (iqp->file, iqp->file_len);
-
- if ((cf2 & IOPARM_INQUIRE_HAS_IQSTREAM) != 0)
- cf_strcpy (iqp->iqstream, iqp->iqstream_len, "UNKNOWN");
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_POSITION) != 0)
- cf_strcpy (iqp->position, iqp->position_len, undefined);
-
- if ((cf & IOPARM_INQUIRE_HAS_ACCESS) != 0)
- cf_strcpy (iqp->access, iqp->access_len, undefined);
-
- if ((cf & IOPARM_INQUIRE_HAS_READ) != 0)
- {
- p = inquire_read (iqp->file, iqp->file_len);
- cf_strcpy (iqp->read, iqp->read_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_WRITE) != 0)
- {
- p = inquire_write (iqp->file, iqp->file_len);
- cf_strcpy (iqp->write, iqp->write_len, p);
- }
-
- if ((cf & IOPARM_INQUIRE_HAS_READWRITE) != 0)
- {
- p = inquire_read (iqp->file, iqp->file_len);
- cf_strcpy (iqp->readwrite, iqp->readwrite_len, p);
- }
-}
-
-
-/* Library entry point for the INQUIRE statement (non-IOLENGTH
- form). */
-
-extern void st_inquire (st_parameter_inquire *);
-export_proto(st_inquire);
-
-void
-st_inquire (st_parameter_inquire *iqp)
-{
- gfc_unit *u;
-
- library_start (&iqp->common);
-
- if ((iqp->common.flags & IOPARM_INQUIRE_HAS_FILE) == 0)
- {
- u = find_unit (iqp->common.unit);
- inquire_via_unit (iqp, u);
- }
- else
- {
- u = find_file (iqp->file, iqp->file_len);
- if (u == NULL)
- inquire_via_filename (iqp);
- else
- inquire_via_unit (iqp, u);
- }
- if (u != NULL)
- unlock_unit (u);
-
- library_end ();
-}
diff --git a/gcc-4.8.1/libgfortran/io/intrinsics.c b/gcc-4.8.1/libgfortran/io/intrinsics.c
deleted file mode 100644
index 1573434d6..000000000
--- a/gcc-4.8.1/libgfortran/io/intrinsics.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/* Implementation of the FGET, FGETC, FPUT, FPUTC, FLUSH
- FTELL, TTYNAM and ISATTY intrinsics.
- Copyright (C) 2005-2013 Free Software Foundation, Inc.
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public
-License as published by the Free Software Foundation; either
-version 3 of the License, or (at your option) any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "io.h"
-#include "fbuf.h"
-#include "unix.h"
-#include <stdlib.h>
-#include <string.h>
-
-
-static const int five = 5;
-static const int six = 6;
-
-extern int PREFIX(fgetc) (const int *, char *, gfc_charlen_type);
-export_proto_np(PREFIX(fgetc));
-
-int
-PREFIX(fgetc) (const int * unit, char * c, gfc_charlen_type c_len)
-{
- int ret;
- gfc_unit * u = find_unit (*unit);
-
- if (u == NULL)
- return -1;
-
- fbuf_reset (u);
- if (u->mode == WRITING)
- {
- sflush (u->s);
- u->mode = READING;
- }
-
- memset (c, ' ', c_len);
- ret = sread (u->s, c, 1);
- unlock_unit (u);
-
- if (ret < 0)
- return ret;
-
- if (ret != 1)
- return -1;
- else
- return 0;
-}
-
-
-#define FGETC_SUB(kind) \
- extern void fgetc_i ## kind ## _sub \
- (const int *, char *, GFC_INTEGER_ ## kind *, gfc_charlen_type); \
- export_proto(fgetc_i ## kind ## _sub); \
- void fgetc_i ## kind ## _sub \
- (const int * unit, char * c, GFC_INTEGER_ ## kind * st, gfc_charlen_type c_len) \
- { if (st != NULL) \
- *st = PREFIX(fgetc) (unit, c, c_len); \
- else \
- PREFIX(fgetc) (unit, c, c_len); }
-
-FGETC_SUB(1)
-FGETC_SUB(2)
-FGETC_SUB(4)
-FGETC_SUB(8)
-
-
-extern int PREFIX(fget) (char *, gfc_charlen_type);
-export_proto_np(PREFIX(fget));
-
-int
-PREFIX(fget) (char * c, gfc_charlen_type c_len)
-{
- return PREFIX(fgetc) (&five, c, c_len);
-}
-
-
-#define FGET_SUB(kind) \
- extern void fget_i ## kind ## _sub \
- (char *, GFC_INTEGER_ ## kind *, gfc_charlen_type); \
- export_proto(fget_i ## kind ## _sub); \
- void fget_i ## kind ## _sub \
- (char * c, GFC_INTEGER_ ## kind * st, gfc_charlen_type c_len) \
- { if (st != NULL) \
- *st = PREFIX(fgetc) (&five, c, c_len); \
- else \
- PREFIX(fgetc) (&five, c, c_len); }
-
-FGET_SUB(1)
-FGET_SUB(2)
-FGET_SUB(4)
-FGET_SUB(8)
-
-
-
-extern int PREFIX(fputc) (const int *, char *, gfc_charlen_type);
-export_proto_np(PREFIX(fputc));
-
-int
-PREFIX(fputc) (const int * unit, char * c,
- gfc_charlen_type c_len __attribute__((unused)))
-{
- ssize_t s;
- gfc_unit * u = find_unit (*unit);
-
- if (u == NULL)
- return -1;
-
- fbuf_reset (u);
- if (u->mode == READING)
- {
- sflush (u->s);
- u->mode = WRITING;
- }
-
- s = swrite (u->s, c, 1);
- unlock_unit (u);
- if (s < 0)
- return -1;
- return 0;
-}
-
-
-#define FPUTC_SUB(kind) \
- extern void fputc_i ## kind ## _sub \
- (const int *, char *, GFC_INTEGER_ ## kind *, gfc_charlen_type); \
- export_proto(fputc_i ## kind ## _sub); \
- void fputc_i ## kind ## _sub \
- (const int * unit, char * c, GFC_INTEGER_ ## kind * st, gfc_charlen_type c_len) \
- { if (st != NULL) \
- *st = PREFIX(fputc) (unit, c, c_len); \
- else \
- PREFIX(fputc) (unit, c, c_len); }
-
-FPUTC_SUB(1)
-FPUTC_SUB(2)
-FPUTC_SUB(4)
-FPUTC_SUB(8)
-
-
-extern int PREFIX(fput) (char *, gfc_charlen_type);
-export_proto_np(PREFIX(fput));
-
-int
-PREFIX(fput) (char * c, gfc_charlen_type c_len)
-{
- return PREFIX(fputc) (&six, c, c_len);
-}
-
-
-#define FPUT_SUB(kind) \
- extern void fput_i ## kind ## _sub \
- (char *, GFC_INTEGER_ ## kind *, gfc_charlen_type); \
- export_proto(fput_i ## kind ## _sub); \
- void fput_i ## kind ## _sub \
- (char * c, GFC_INTEGER_ ## kind * st, gfc_charlen_type c_len) \
- { if (st != NULL) \
- *st = PREFIX(fputc) (&six, c, c_len); \
- else \
- PREFIX(fputc) (&six, c, c_len); }
-
-FPUT_SUB(1)
-FPUT_SUB(2)
-FPUT_SUB(4)
-FPUT_SUB(8)
-
-
-/* SUBROUTINE FLUSH(UNIT)
- INTEGER, INTENT(IN), OPTIONAL :: UNIT */
-
-extern void flush_i4 (GFC_INTEGER_4 *);
-export_proto(flush_i4);
-
-void
-flush_i4 (GFC_INTEGER_4 *unit)
-{
- gfc_unit *us;
-
- /* flush all streams */
- if (unit == NULL)
- flush_all_units ();
- else
- {
- us = find_unit (*unit);
- if (us != NULL)
- {
- sflush (us->s);
- unlock_unit (us);
- }
- }
-}
-
-
-extern void flush_i8 (GFC_INTEGER_8 *);
-export_proto(flush_i8);
-
-void
-flush_i8 (GFC_INTEGER_8 *unit)
-{
- gfc_unit *us;
-
- /* flush all streams */
- if (unit == NULL)
- flush_all_units ();
- else
- {
- us = find_unit (*unit);
- if (us != NULL)
- {
- sflush (us->s);
- unlock_unit (us);
- }
- }
-}
-
-/* FSEEK intrinsic */
-
-extern void fseek_sub (int *, GFC_IO_INT *, int *, int *);
-export_proto(fseek_sub);
-
-void
-fseek_sub (int * unit, GFC_IO_INT * offset, int * whence, int * status)
-{
- gfc_unit * u = find_unit (*unit);
- ssize_t result = -1;
-
- if (u != NULL)
- {
- result = sseek(u->s, *offset, *whence);
-
- unlock_unit (u);
- }
-
- if (status)
- *status = (result < 0 ? -1 : 0);
-}
-
-
-
-/* FTELL intrinsic */
-
-static gfc_offset
-gf_ftell (int unit)
-{
- gfc_unit * u = find_unit (unit);
- if (u == NULL)
- return -1;
- int pos = fbuf_reset (u);
- if (pos != 0)
- sseek (u->s, pos, SEEK_CUR);
- gfc_offset ret = stell (u->s);
- unlock_unit (u);
- return ret;
-}
-
-
-/* Here is the ftell function with an incorrect return type; retained
- due to ABI compatibility. */
-
-extern size_t PREFIX(ftell) (int *);
-export_proto_np(PREFIX(ftell));
-
-size_t
-PREFIX(ftell) (int * unit)
-{
- return gf_ftell (*unit);
-}
-
-
-/* Here is the ftell function with the correct return type, ensuring
- that large files can be supported as long as the target supports
- large integers; as of 4.8 the FTELL intrinsic function will call
- this one instead of the old ftell above. */
-
-extern GFC_IO_INT PREFIX(ftell2) (int *);
-export_proto_np(PREFIX(ftell2));
-
-GFC_IO_INT
-PREFIX(ftell2) (int * unit)
-{
- return gf_ftell (*unit);
-}
-
-
-#define FTELL_SUB(kind) \
- extern void ftell_i ## kind ## _sub (int *, GFC_INTEGER_ ## kind *); \
- export_proto(ftell_i ## kind ## _sub); \
- void \
- ftell_i ## kind ## _sub (int * unit, GFC_INTEGER_ ## kind * offset) \
- { \
- *offset = gf_ftell (*unit); \
- }
-
-FTELL_SUB(1)
-FTELL_SUB(2)
-FTELL_SUB(4)
-FTELL_SUB(8)
-
-
-
-/* LOGICAL FUNCTION ISATTY(UNIT)
- INTEGER, INTENT(IN) :: UNIT */
-
-extern GFC_LOGICAL_4 isatty_l4 (int *);
-export_proto(isatty_l4);
-
-GFC_LOGICAL_4
-isatty_l4 (int *unit)
-{
- gfc_unit *u;
- GFC_LOGICAL_4 ret = 0;
-
- u = find_unit (*unit);
- if (u != NULL)
- {
- ret = (GFC_LOGICAL_4) stream_isatty (u->s);
- unlock_unit (u);
- }
- return ret;
-}
-
-
-extern GFC_LOGICAL_8 isatty_l8 (int *);
-export_proto(isatty_l8);
-
-GFC_LOGICAL_8
-isatty_l8 (int *unit)
-{
- gfc_unit *u;
- GFC_LOGICAL_8 ret = 0;
-
- u = find_unit (*unit);
- if (u != NULL)
- {
- ret = (GFC_LOGICAL_8) stream_isatty (u->s);
- unlock_unit (u);
- }
- return ret;
-}
-
-
-/* SUBROUTINE TTYNAM(UNIT,NAME)
- INTEGER,SCALAR,INTENT(IN) :: UNIT
- CHARACTER,SCALAR,INTENT(OUT) :: NAME */
-
-extern void ttynam_sub (int *, char *, gfc_charlen_type);
-export_proto(ttynam_sub);
-
-void
-ttynam_sub (int *unit, char * name, gfc_charlen_type name_len)
-{
- gfc_unit *u;
- int nlen;
- int err = 1;
-
- u = find_unit (*unit);
- if (u != NULL)
- {
- err = stream_ttyname (u->s, name, name_len);
- if (err == 0)
- {
- nlen = strlen (name);
- memset (&name[nlen], ' ', name_len - nlen);
- }
-
- unlock_unit (u);
- }
- if (err != 0)
- memset (name, ' ', name_len);
-}
-
-
-extern void ttynam (char **, gfc_charlen_type *, int);
-export_proto(ttynam);
-
-void
-ttynam (char ** name, gfc_charlen_type * name_len, int unit)
-{
- gfc_unit *u;
-
- u = find_unit (unit);
- if (u != NULL)
- {
- *name = xmalloc (TTY_NAME_MAX);
- int err = stream_ttyname (u->s, *name, TTY_NAME_MAX);
- if (err == 0)
- {
- *name_len = strlen (*name);
- unlock_unit (u);
- return;
- }
- free (*name);
- unlock_unit (u);
- }
-
- *name_len = 0;
- *name = NULL;
-}
diff --git a/gcc-4.8.1/libgfortran/io/io.h b/gcc-4.8.1/libgfortran/io/io.h
deleted file mode 100644
index 8ea932667..000000000
--- a/gcc-4.8.1/libgfortran/io/io.h
+++ /dev/null
@@ -1,811 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef GFOR_IO_H
-#define GFOR_IO_H
-
-/* IO library include. */
-
-#include "libgfortran.h"
-
-#include <gthr.h>
-
-/* Forward declarations. */
-struct st_parameter_dt;
-typedef struct stream stream;
-struct fbuf;
-struct format_data;
-typedef struct fnode fnode;
-struct gfc_unit;
-
-
-/* Macros for testing what kinds of I/O we are doing. */
-
-#define is_array_io(dtp) ((dtp)->internal_unit_desc)
-
-#define is_internal_unit(dtp) ((dtp)->u.p.unit_is_internal)
-
-#define is_stream_io(dtp) ((dtp)->u.p.current_unit->flags.access == ACCESS_STREAM)
-
-#define is_char4_unit(dtp) ((dtp)->u.p.unit_is_internal && (dtp)->common.unit)
-
-/* The array_loop_spec contains the variables for the loops over index ranges
- that are encountered. */
-
-typedef struct array_loop_spec
-{
- /* Index counter for this dimension. */
- index_type idx;
-
- /* Start for the index counter. */
- index_type start;
-
- /* End for the index counter. */
- index_type end;
-
- /* Step for the index counter. */
- index_type step;
-}
-array_loop_spec;
-
-/* A structure to build a hash table for format data. */
-
-#define FORMAT_HASH_SIZE 16
-
-typedef struct format_hash_entry
-{
- char *key;
- gfc_charlen_type key_len;
- struct format_data *hashed_fmt;
-}
-format_hash_entry;
-
-/* Representation of a namelist object in libgfortran
-
- Namelist Records
- &GROUPNAME OBJECT=value[s] [,OBJECT=value[s]].../
- or
- &GROUPNAME OBJECT=value[s] [,OBJECT=value[s]]...&END
-
- The object can be a fully qualified, compound name for an intrinsic
- type, derived types or derived type components. So, a substring
- a(:)%b(4)%ch(2:4)(1:7) has to be treated correctly in namelist
- read. Hence full information about the structure of the object has
- to be available to list_read.c and write.
-
- These requirements are met by the following data structures.
-
- namelist_info type contains all the scalar information about the
- object and arrays of descriptor_dimension and array_loop_spec types for
- arrays. */
-
-typedef struct namelist_type
-{
- /* Object type. */
- bt type;
-
- /* Object name. */
- char * var_name;
-
- /* Address for the start of the object's data. */
- void * mem_pos;
-
- /* Flag to show that a read is to be attempted for this node. */
- int touched;
-
- /* Length of intrinsic type in bytes. */
- int len;
-
- /* Rank of the object. */
- int var_rank;
-
- /* Overall size of the object in bytes. */
- index_type size;
-
- /* Length of character string. */
- index_type string_length;
-
- descriptor_dimension * dim;
- array_loop_spec * ls;
- struct namelist_type * next;
-}
-namelist_info;
-
-/* Options for the OPEN statement. */
-
-typedef enum
-{ ACCESS_SEQUENTIAL, ACCESS_DIRECT, ACCESS_APPEND, ACCESS_STREAM,
- ACCESS_UNSPECIFIED
-}
-unit_access;
-
-typedef enum
-{ ACTION_READ, ACTION_WRITE, ACTION_READWRITE,
- ACTION_UNSPECIFIED
-}
-unit_action;
-
-typedef enum
-{ BLANK_NULL, BLANK_ZERO, BLANK_UNSPECIFIED }
-unit_blank;
-
-typedef enum
-{ DELIM_NONE, DELIM_APOSTROPHE, DELIM_QUOTE,
- DELIM_UNSPECIFIED
-}
-unit_delim;
-
-typedef enum
-{ FORM_FORMATTED, FORM_UNFORMATTED, FORM_UNSPECIFIED }
-unit_form;
-
-typedef enum
-{ POSITION_ASIS, POSITION_REWIND, POSITION_APPEND,
- POSITION_UNSPECIFIED
-}
-unit_position;
-
-typedef enum
-{ STATUS_UNKNOWN, STATUS_OLD, STATUS_NEW, STATUS_SCRATCH,
- STATUS_REPLACE, STATUS_UNSPECIFIED
-}
-unit_status;
-
-typedef enum
-{ PAD_YES, PAD_NO, PAD_UNSPECIFIED }
-unit_pad;
-
-typedef enum
-{ DECIMAL_POINT, DECIMAL_COMMA, DECIMAL_UNSPECIFIED }
-unit_decimal;
-
-typedef enum
-{ ENCODING_UTF8, ENCODING_DEFAULT, ENCODING_UNSPECIFIED }
-unit_encoding;
-
-typedef enum
-{ ROUND_UP, ROUND_DOWN, ROUND_ZERO, ROUND_NEAREST, ROUND_COMPATIBLE,
- ROUND_PROCDEFINED, ROUND_UNSPECIFIED }
-unit_round;
-
-/* NOTE: unit_sign must correspond with the sign_status enumerator in
- st_parameter_dt to not break the ABI. */
-typedef enum
-{ SIGN_PROCDEFINED, SIGN_SUPPRESS, SIGN_PLUS, SIGN_UNSPECIFIED }
-unit_sign;
-
-typedef enum
-{ ADVANCE_YES, ADVANCE_NO, ADVANCE_UNSPECIFIED }
-unit_advance;
-
-typedef enum
-{READING, WRITING}
-unit_mode;
-
-typedef enum
-{ ASYNC_YES, ASYNC_NO, ASYNC_UNSPECIFIED }
-unit_async;
-
-typedef enum
-{ SIGN_S, SIGN_SS, SIGN_SP }
-unit_sign_s;
-
-#define CHARACTER1(name) \
- char * name; \
- gfc_charlen_type name ## _len
-#define CHARACTER2(name) \
- gfc_charlen_type name ## _len; \
- char * name
-
-typedef struct
-{
- st_parameter_common common;
- GFC_INTEGER_4 recl_in;
- CHARACTER2 (file);
- CHARACTER1 (status);
- CHARACTER2 (access);
- CHARACTER1 (form);
- CHARACTER2 (blank);
- CHARACTER1 (position);
- CHARACTER2 (action);
- CHARACTER1 (delim);
- CHARACTER2 (pad);
- CHARACTER1 (convert);
- CHARACTER2 (decimal);
- CHARACTER1 (encoding);
- CHARACTER2 (round);
- CHARACTER1 (sign);
- CHARACTER2 (asynchronous);
- GFC_INTEGER_4 *newunit;
-}
-st_parameter_open;
-
-#define IOPARM_CLOSE_HAS_STATUS (1 << 7)
-
-typedef struct
-{
- st_parameter_common common;
- CHARACTER1 (status);
-}
-st_parameter_close;
-
-typedef struct
-{
- st_parameter_common common;
-}
-st_parameter_filepos;
-
-#define IOPARM_INQUIRE_HAS_EXIST (1 << 7)
-#define IOPARM_INQUIRE_HAS_OPENED (1 << 8)
-#define IOPARM_INQUIRE_HAS_NUMBER (1 << 9)
-#define IOPARM_INQUIRE_HAS_NAMED (1 << 10)
-#define IOPARM_INQUIRE_HAS_NEXTREC (1 << 11)
-#define IOPARM_INQUIRE_HAS_RECL_OUT (1 << 12)
-#define IOPARM_INQUIRE_HAS_STRM_POS_OUT (1 << 13)
-#define IOPARM_INQUIRE_HAS_FILE (1 << 14)
-#define IOPARM_INQUIRE_HAS_ACCESS (1 << 15)
-#define IOPARM_INQUIRE_HAS_FORM (1 << 16)
-#define IOPARM_INQUIRE_HAS_BLANK (1 << 17)
-#define IOPARM_INQUIRE_HAS_POSITION (1 << 18)
-#define IOPARM_INQUIRE_HAS_ACTION (1 << 19)
-#define IOPARM_INQUIRE_HAS_DELIM (1 << 20)
-#define IOPARM_INQUIRE_HAS_PAD (1 << 21)
-#define IOPARM_INQUIRE_HAS_NAME (1 << 22)
-#define IOPARM_INQUIRE_HAS_SEQUENTIAL (1 << 23)
-#define IOPARM_INQUIRE_HAS_DIRECT (1 << 24)
-#define IOPARM_INQUIRE_HAS_FORMATTED (1 << 25)
-#define IOPARM_INQUIRE_HAS_UNFORMATTED (1 << 26)
-#define IOPARM_INQUIRE_HAS_READ (1 << 27)
-#define IOPARM_INQUIRE_HAS_WRITE (1 << 28)
-#define IOPARM_INQUIRE_HAS_READWRITE (1 << 29)
-#define IOPARM_INQUIRE_HAS_CONVERT (1 << 30)
-#define IOPARM_INQUIRE_HAS_FLAGS2 (1 << 31)
-
-#define IOPARM_INQUIRE_HAS_ASYNCHRONOUS (1 << 0)
-#define IOPARM_INQUIRE_HAS_DECIMAL (1 << 1)
-#define IOPARM_INQUIRE_HAS_ENCODING (1 << 2)
-#define IOPARM_INQUIRE_HAS_ROUND (1 << 3)
-#define IOPARM_INQUIRE_HAS_SIGN (1 << 4)
-#define IOPARM_INQUIRE_HAS_PENDING (1 << 5)
-#define IOPARM_INQUIRE_HAS_SIZE (1 << 6)
-#define IOPARM_INQUIRE_HAS_ID (1 << 7)
-#define IOPARM_INQUIRE_HAS_IQSTREAM (1 << 8)
-
-typedef struct
-{
- st_parameter_common common;
- GFC_INTEGER_4 *exist, *opened, *number, *named;
- GFC_INTEGER_4 *nextrec, *recl_out;
- GFC_IO_INT *strm_pos_out;
- CHARACTER1 (file);
- CHARACTER2 (access);
- CHARACTER1 (form);
- CHARACTER2 (blank);
- CHARACTER1 (position);
- CHARACTER2 (action);
- CHARACTER1 (delim);
- CHARACTER2 (pad);
- CHARACTER1 (name);
- CHARACTER2 (sequential);
- CHARACTER1 (direct);
- CHARACTER2 (formatted);
- CHARACTER1 (unformatted);
- CHARACTER2 (read);
- CHARACTER1 (write);
- CHARACTER2 (readwrite);
- CHARACTER1 (convert);
- GFC_INTEGER_4 flags2;
- CHARACTER1 (asynchronous);
- CHARACTER2 (decimal);
- CHARACTER1 (encoding);
- CHARACTER2 (round);
- CHARACTER1 (sign);
- GFC_INTEGER_4 *pending;
- GFC_IO_INT *size;
- GFC_INTEGER_4 *id;
- CHARACTER1 (iqstream);
-}
-st_parameter_inquire;
-
-
-#define IOPARM_DT_LIST_FORMAT (1 << 7)
-#define IOPARM_DT_NAMELIST_READ_MODE (1 << 8)
-#define IOPARM_DT_HAS_REC (1 << 9)
-#define IOPARM_DT_HAS_SIZE (1 << 10)
-#define IOPARM_DT_HAS_IOLENGTH (1 << 11)
-#define IOPARM_DT_HAS_FORMAT (1 << 12)
-#define IOPARM_DT_HAS_ADVANCE (1 << 13)
-#define IOPARM_DT_HAS_INTERNAL_UNIT (1 << 14)
-#define IOPARM_DT_HAS_NAMELIST_NAME (1 << 15)
-#define IOPARM_DT_HAS_ID (1 << 16)
-#define IOPARM_DT_HAS_POS (1 << 17)
-#define IOPARM_DT_HAS_ASYNCHRONOUS (1 << 18)
-#define IOPARM_DT_HAS_BLANK (1 << 19)
-#define IOPARM_DT_HAS_DECIMAL (1 << 20)
-#define IOPARM_DT_HAS_DELIM (1 << 21)
-#define IOPARM_DT_HAS_PAD (1 << 22)
-#define IOPARM_DT_HAS_ROUND (1 << 23)
-#define IOPARM_DT_HAS_SIGN (1 << 24)
-#define IOPARM_DT_HAS_F2003 (1 << 25)
-/* Internal use bit. */
-#define IOPARM_DT_IONML_SET (1 << 31)
-
-
-typedef struct st_parameter_dt
-{
- st_parameter_common common;
- GFC_IO_INT rec;
- GFC_IO_INT *size, *iolength;
- gfc_array_char *internal_unit_desc;
- CHARACTER1 (format);
- CHARACTER2 (advance);
- CHARACTER1 (internal_unit);
- CHARACTER2 (namelist_name);
- /* Private part of the structure. The compiler just needs
- to reserve enough space. */
- union
- {
- struct
- {
- void (*transfer) (struct st_parameter_dt *, bt, void *, int,
- size_t, size_t);
- struct gfc_unit *current_unit;
- /* Item number in a formatted data transfer. Also used in namelist
- read_logical as an index into line_buffer. */
- int item_count;
- unit_mode mode;
- unit_blank blank_status;
- unit_sign sign_status;
- int scale_factor;
- int max_pos; /* Maximum righthand column written to. */
- /* Number of skips + spaces to be done for T and X-editing. */
- int skips;
- /* Number of spaces to be done for T and X-editing. */
- int pending_spaces;
- /* Whether an EOR condition was encountered. Value is:
- 0 if no EOR was encountered
- 1 if an EOR was encountered due to a 1-byte marker (LF)
- 2 if an EOR was encountered due to a 2-bytes marker (CRLF) */
- int sf_seen_eor;
- unit_advance advance_status;
- unsigned reversion_flag : 1; /* Format reversion has occurred. */
- unsigned first_item : 1;
- unsigned seen_dollar : 1;
- unsigned eor_condition : 1;
- unsigned no_leading_blank : 1;
- unsigned char_flag : 1;
- unsigned input_complete : 1;
- unsigned at_eol : 1;
- unsigned comma_flag : 1;
- /* A namelist specific flag used in the list directed library
- to flag that calls are being made from namelist read (e.g. to
- ignore comments or to treat '/' as a terminator) */
- unsigned namelist_mode : 1;
- /* A namelist specific flag used in the list directed library
- to flag read errors and return, so that an attempt can be
- made to read a new object name. */
- unsigned nml_read_error : 1;
- /* A sequential formatted read specific flag used to signal that a
- character string is being read so don't use commas to shorten a
- formatted field width. */
- unsigned sf_read_comma : 1;
- /* A namelist specific flag used to enable reading input from
- line_buffer for logical reads. */
- unsigned line_buffer_enabled : 1;
- /* An internal unit specific flag used to identify that the associated
- unit is internal. */
- unsigned unit_is_internal : 1;
- /* An internal unit specific flag to signify an EOF condition for list
- directed read. */
- unsigned at_eof : 1;
- /* Used for g0 floating point output. */
- unsigned g0_no_blanks : 1;
- /* Used to signal use of free_format_data. */
- unsigned format_not_saved : 1;
- /* 14 unused bits. */
-
- /* Used for ungetc() style functionality. Possible values
- are an unsigned char, EOF, or EOF - 1 used to mark the
- field as not valid. */
- int last_char;
- char nml_delim;
-
- int repeat_count;
- int saved_length;
- int saved_used;
- bt saved_type;
- char *saved_string;
- char *scratch;
- char *line_buffer;
- struct format_data *fmt;
- namelist_info *ionml;
- /* A flag used to identify when a non-standard expanded namelist read
- has occurred. */
- int expanded_read;
- /* Storage area for values except for strings. Must be
- large enough to hold a complex value (two reals) of the
- largest kind. */
- char value[32];
- GFC_IO_INT size_used;
- } p;
- /* This pad size must be equal to the pad_size declared in
- trans-io.c (gfc_build_io_library_fndecls). The above structure
- must be smaller or equal to this array. */
- char pad[16 * sizeof (char *) + 32 * sizeof (int)];
- } u;
- GFC_INTEGER_4 *id;
- GFC_IO_INT pos;
- CHARACTER1 (asynchronous);
- CHARACTER2 (blank);
- CHARACTER1 (decimal);
- CHARACTER2 (delim);
- CHARACTER1 (pad);
- CHARACTER2 (round);
- CHARACTER1 (sign);
-}
-st_parameter_dt;
-
-/* Ensure st_parameter_dt's u.pad is bigger or equal to u.p. */
-extern char check_st_parameter_dt[sizeof (((st_parameter_dt *) 0)->u.pad)
- >= sizeof (((st_parameter_dt *) 0)->u.p)
- ? 1 : -1];
-
-#define IOPARM_WAIT_HAS_ID (1 << 7)
-
-typedef struct
-{
- st_parameter_common common;
- CHARACTER1 (id);
-}
-st_parameter_wait;
-
-
-#undef CHARACTER1
-#undef CHARACTER2
-
-typedef struct
-{
- unit_access access;
- unit_action action;
- unit_blank blank;
- unit_delim delim;
- unit_form form;
- int is_notpadded;
- unit_position position;
- unit_status status;
- unit_pad pad;
- unit_convert convert;
- int has_recl;
- unit_decimal decimal;
- unit_encoding encoding;
- unit_round round;
- unit_sign sign;
- unit_async async;
-}
-unit_flags;
-
-
-typedef struct gfc_unit
-{
- int unit_number;
- stream *s;
-
- /* Treap links. */
- struct gfc_unit *left, *right;
- int priority;
-
- int read_bad, current_record, saved_pos, previous_nonadvancing_write;
-
- enum
- { NO_ENDFILE, AT_ENDFILE, AFTER_ENDFILE }
- endfile;
-
- unit_mode mode;
- unit_flags flags;
- unit_pad pad_status;
- unit_decimal decimal_status;
- unit_delim delim_status;
- unit_round round_status;
-
- /* recl -- Record length of the file.
- last_record -- Last record number read or written
- maxrec -- Maximum record number in a direct access file
- bytes_left -- Bytes left in current record.
- strm_pos -- Current position in file for STREAM I/O.
- recl_subrecord -- Maximum length for subrecord.
- bytes_left_subrecord -- Bytes left in current subrecord. */
- gfc_offset recl, last_record, maxrec, bytes_left, strm_pos,
- recl_subrecord, bytes_left_subrecord;
-
- /* Set to 1 if we have read a subrecord. */
-
- int continued;
-
- __gthread_mutex_t lock;
- /* Number of threads waiting to acquire this unit's lock.
- When non-zero, close_unit doesn't only removes the unit
- from the UNIT_ROOT tree, but doesn't free it and the
- last of the waiting threads will do that.
- This must be either atomically increased/decreased, or
- always guarded by UNIT_LOCK. */
- int waiting;
- /* Flag set by close_unit if the unit as been closed.
- Must be manipulated under unit's lock. */
- int closed;
-
- /* For traversing arrays */
- array_loop_spec *ls;
- int rank;
-
- int file_len;
- char *file;
-
- /* The format hash table. */
- struct format_hash_entry format_hash_table[FORMAT_HASH_SIZE];
-
- /* Formatting buffer. */
- struct fbuf *fbuf;
-}
-gfc_unit;
-
-
-/* unit.c */
-
-/* Maximum file offset, computed at library initialization time. */
-extern gfc_offset max_offset;
-internal_proto(max_offset);
-
-/* Unit tree root. */
-extern gfc_unit *unit_root;
-internal_proto(unit_root);
-
-extern __gthread_mutex_t unit_lock;
-internal_proto(unit_lock);
-
-extern int close_unit (gfc_unit *);
-internal_proto(close_unit);
-
-extern gfc_unit *get_internal_unit (st_parameter_dt *);
-internal_proto(get_internal_unit);
-
-extern void free_internal_unit (st_parameter_dt *);
-internal_proto(free_internal_unit);
-
-extern gfc_unit *find_unit (int);
-internal_proto(find_unit);
-
-extern gfc_unit *find_or_create_unit (int);
-internal_proto(find_or_create_unit);
-
-extern gfc_unit *get_unit (st_parameter_dt *, int);
-internal_proto(get_unit);
-
-extern void unlock_unit (gfc_unit *);
-internal_proto(unlock_unit);
-
-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);
-
-extern GFC_INTEGER_4 get_unique_unit_number (st_parameter_open *);
-internal_proto(get_unique_unit_number);
-
-/* open.c */
-
-extern gfc_unit *new_unit (st_parameter_open *, gfc_unit *, unit_flags *);
-internal_proto(new_unit);
-
-
-/* transfer.c */
-
-#define SCRATCH_SIZE 300
-
-extern const char *type_name (bt);
-internal_proto(type_name);
-
-extern void * read_block_form (st_parameter_dt *, int *);
-internal_proto(read_block_form);
-
-extern void * read_block_form4 (st_parameter_dt *, int *);
-internal_proto(read_block_form4);
-
-extern void *write_block (st_parameter_dt *, int);
-internal_proto(write_block);
-
-extern gfc_offset next_array_record (st_parameter_dt *, array_loop_spec *,
- int*);
-internal_proto(next_array_record);
-
-extern gfc_offset init_loop_spec (gfc_array_char *, array_loop_spec *,
- gfc_offset *);
-internal_proto(init_loop_spec);
-
-extern void next_record (st_parameter_dt *, int);
-internal_proto(next_record);
-
-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);
-internal_proto(set_integer);
-
-extern GFC_UINTEGER_LARGEST si_max (int);
-internal_proto(si_max);
-
-extern int convert_real (st_parameter_dt *, void *, const char *, int);
-internal_proto(convert_real);
-
-extern int convert_infnan (st_parameter_dt *, void *, const char *, int);
-internal_proto(convert_infnan);
-
-extern void read_a (st_parameter_dt *, const fnode *, char *, int);
-internal_proto(read_a);
-
-extern void read_a_char4 (st_parameter_dt *, const fnode *, char *, int);
-internal_proto(read_a);
-
-extern void read_f (st_parameter_dt *, const fnode *, char *, int);
-internal_proto(read_f);
-
-extern void read_l (st_parameter_dt *, const fnode *, char *, int);
-internal_proto(read_l);
-
-extern void read_x (st_parameter_dt *, int);
-internal_proto(read_x);
-
-extern void read_radix (st_parameter_dt *, const fnode *, char *, int, int);
-internal_proto(read_radix);
-
-extern void read_decimal (st_parameter_dt *, const fnode *, char *, int);
-internal_proto(read_decimal);
-
-/* list_read.c */
-
-extern void list_formatted_read (st_parameter_dt *, bt, void *, int, size_t,
- size_t);
-internal_proto(list_formatted_read);
-
-extern void finish_list_read (st_parameter_dt *);
-internal_proto(finish_list_read);
-
-extern void namelist_read (st_parameter_dt *);
-internal_proto(namelist_read);
-
-extern void namelist_write (st_parameter_dt *);
-internal_proto(namelist_write);
-
-/* write.c */
-
-extern void write_a (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_a);
-
-extern void write_a_char4 (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_a_char4);
-
-extern void write_b (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_b);
-
-extern void write_d (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_d);
-
-extern void write_e (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_e);
-
-extern void write_en (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_en);
-
-extern void write_es (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_es);
-
-extern void write_f (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_f);
-
-extern void write_i (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_i);
-
-extern void write_l (st_parameter_dt *, const fnode *, char *, int);
-internal_proto(write_l);
-
-extern void write_o (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_o);
-
-extern void write_real (st_parameter_dt *, const char *, int);
-internal_proto(write_real);
-
-extern void write_real_g0 (st_parameter_dt *, const char *, int, int);
-internal_proto(write_real_g0);
-
-extern void write_x (st_parameter_dt *, int, int);
-internal_proto(write_x);
-
-extern void write_z (st_parameter_dt *, const fnode *, const char *, int);
-internal_proto(write_z);
-
-extern void list_formatted_write (st_parameter_dt *, bt, void *, int, size_t,
- size_t);
-internal_proto(list_formatted_write);
-
-/* size_from_kind.c */
-extern size_t size_from_real_kind (int);
-internal_proto(size_from_real_kind);
-
-extern size_t size_from_complex_kind (int);
-internal_proto(size_from_complex_kind);
-
-
-/* lock.c */
-extern void free_ionml (st_parameter_dt *);
-internal_proto(free_ionml);
-
-static inline void
-inc_waiting_locked (gfc_unit *u)
-{
-#ifdef HAVE_SYNC_FETCH_AND_ADD
- (void) __sync_fetch_and_add (&u->waiting, 1);
-#else
- u->waiting++;
-#endif
-}
-
-static inline int
-predec_waiting_locked (gfc_unit *u)
-{
-#ifdef HAVE_SYNC_FETCH_AND_ADD
- return __sync_add_and_fetch (&u->waiting, -1);
-#else
- return --u->waiting;
-#endif
-}
-
-static inline void
-dec_waiting_unlocked (gfc_unit *u)
-{
-#ifdef HAVE_SYNC_FETCH_AND_ADD
- (void) __sync_fetch_and_add (&u->waiting, -1);
-#else
- __gthread_mutex_lock (&unit_lock);
- u->waiting--;
- __gthread_mutex_unlock (&unit_lock);
-#endif
-}
-
-
-static inline void
-memset4 (gfc_char4_t *p, gfc_char4_t c, int k)
-{
- int j;
- for (j = 0; j < k; j++)
- *p++ = c;
-}
-
-#endif
-
diff --git a/gcc-4.8.1/libgfortran/io/list_read.c b/gcc-4.8.1/libgfortran/io/list_read.c
deleted file mode 100644
index 5a44bdf78..000000000
--- a/gcc-4.8.1/libgfortran/io/list_read.c
+++ /dev/null
@@ -1,3155 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- Namelist input contributed by Paul Thomas
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-
-#include "io.h"
-#include "fbuf.h"
-#include "unix.h"
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-
-/* List directed input. Several parsing subroutines are practically
- reimplemented from formatted input, the reason being that there are
- all kinds of small differences between formatted and list directed
- parsing. */
-
-
-/* Subroutines for reading characters from the input. Because a
- repeat count is ambiguous with an integer, we have to read the
- whole digit string before seeing if there is a '*' which signals
- the repeat count. Since we can have a lot of potential leading
- zeros, we have to be able to back up by arbitrary amount. Because
- the input might not be seekable, we have to buffer the data
- ourselves. */
-
-#define CASE_DIGITS case '0': case '1': case '2': case '3': case '4': \
- case '5': case '6': case '7': case '8': case '9'
-
-#define CASE_SEPARATORS case ' ': case ',': case '/': case '\n': case '\t': \
- case '\r': case ';'
-
-/* This macro assumes that we're operating on a variable. */
-
-#define is_separator(c) (c == '/' || c == ',' || c == '\n' || c == ' ' \
- || c == '\t' || c == '\r' || c == ';')
-
-/* Maximum repeat count. Less than ten times the maximum signed int32. */
-
-#define MAX_REPEAT 200000000
-
-
-#define MSGLEN 100
-
-/* Save a character to a string buffer, enlarging it as necessary. */
-
-static void
-push_char (st_parameter_dt *dtp, char c)
-{
- char *new;
-
- if (dtp->u.p.saved_string == NULL)
- {
- // Plain malloc should suffice here, zeroing not needed?
- dtp->u.p.saved_string = xcalloc (SCRATCH_SIZE, 1);
- dtp->u.p.saved_length = SCRATCH_SIZE;
- dtp->u.p.saved_used = 0;
- }
-
- if (dtp->u.p.saved_used >= dtp->u.p.saved_length)
- {
- dtp->u.p.saved_length = 2 * dtp->u.p.saved_length;
- 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;
-}
-
-
-/* Free the input buffer if necessary. */
-
-static void
-free_saved (st_parameter_dt *dtp)
-{
- if (dtp->u.p.saved_string == NULL)
- return;
-
- free (dtp->u.p.saved_string);
-
- dtp->u.p.saved_string = NULL;
- dtp->u.p.saved_used = 0;
-}
-
-
-/* Free the line buffer if necessary. */
-
-static void
-free_line (st_parameter_dt *dtp)
-{
- dtp->u.p.item_count = 0;
- dtp->u.p.line_buffer_enabled = 0;
-
- if (dtp->u.p.line_buffer == NULL)
- return;
-
- free (dtp->u.p.line_buffer);
- dtp->u.p.line_buffer = NULL;
-}
-
-
-static int
-next_char (st_parameter_dt *dtp)
-{
- ssize_t length;
- gfc_offset record;
- int c;
-
- if (dtp->u.p.last_char != EOF - 1)
- {
- dtp->u.p.at_eol = 0;
- c = dtp->u.p.last_char;
- dtp->u.p.last_char = EOF - 1;
- goto done;
- }
-
- /* Read from line_buffer if enabled. */
-
- if (dtp->u.p.line_buffer_enabled)
- {
- dtp->u.p.at_eol = 0;
-
- c = dtp->u.p.line_buffer[dtp->u.p.item_count];
- if (c != '\0' && dtp->u.p.item_count < 64)
- {
- dtp->u.p.line_buffer[dtp->u.p.item_count] = '\0';
- dtp->u.p.item_count++;
- goto done;
- }
-
- dtp->u.p.item_count = 0;
- dtp->u.p.line_buffer_enabled = 0;
- }
-
- /* Handle the end-of-record and end-of-file conditions for
- internal array unit. */
- if (is_array_io (dtp))
- {
- if (dtp->u.p.at_eof)
- return EOF;
-
- /* Check for "end-of-record" condition. */
- if (dtp->u.p.current_unit->bytes_left == 0)
- {
- int finished;
-
- c = '\n';
- record = next_array_record (dtp, dtp->u.p.current_unit->ls,
- &finished);
-
- /* Check for "end-of-file" condition. */
- if (finished)
- {
- dtp->u.p.at_eof = 1;
- goto done;
- }
-
- record *= dtp->u.p.current_unit->recl;
- if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
- return EOF;
-
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
- goto done;
- }
- }
-
- /* Get the next character and handle end-of-record conditions. */
-
- if (is_internal_unit (dtp))
- {
- /* Check for kind=4 internal unit. */
- if (dtp->common.unit)
- length = sread (dtp->u.p.current_unit->s, &c, sizeof (gfc_char4_t));
- else
- {
- char cc;
- length = sread (dtp->u.p.current_unit->s, &cc, 1);
- c = cc;
- }
-
- if (length < 0)
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return '\0';
- }
-
- if (is_array_io (dtp))
- {
- /* Check whether we hit EOF. */
- if (length == 0)
- {
- generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
- return '\0';
- }
- dtp->u.p.current_unit->bytes_left--;
- }
- else
- {
- if (dtp->u.p.at_eof)
- return EOF;
- if (length == 0)
- {
- c = '\n';
- dtp->u.p.at_eof = 1;
- }
- }
- }
- else
- {
- c = fbuf_getc (dtp->u.p.current_unit);
- if (c != EOF && is_stream_io (dtp))
- dtp->u.p.current_unit->strm_pos++;
- }
-done:
- dtp->u.p.at_eol = (c == '\n' || c == '\r' || c == EOF);
- return c;
-}
-
-
-/* Push a character back onto the input. */
-
-static void
-unget_char (st_parameter_dt *dtp, int c)
-{
- dtp->u.p.last_char = c;
-}
-
-
-/* Skip over spaces in the input. Returns the nonspace character that
- terminated the eating and also places it back on the input. */
-
-static int
-eat_spaces (st_parameter_dt *dtp)
-{
- int c;
-
- do
- c = next_char (dtp);
- while (c != EOF && (c == ' ' || c == '\t'));
-
- unget_char (dtp, c);
- return c;
-}
-
-
-/* This function reads characters through to the end of the current
- line and just ignores them. Returns 0 for success and LIBERROR_END
- if it hit EOF. */
-
-static int
-eat_line (st_parameter_dt *dtp)
-{
- int c;
-
- do
- c = next_char (dtp);
- while (c != EOF && c != '\n');
- if (c == EOF)
- return LIBERROR_END;
- return 0;
-}
-
-
-/* Skip over a separator. Technically, we don't always eat the whole
- separator. This is because if we've processed the last input item,
- then a separator is unnecessary. Plus the fact that operating
- systems usually deliver console input on a line basis.
-
- The upshot is that if we see a newline as part of reading a
- separator, we stop reading. If there are more input items, we
- continue reading the separator with finish_separator() which takes
- care of the fact that we may or may not have seen a comma as part
- of the separator.
-
- Returns 0 for success, and non-zero error code otherwise. */
-
-static int
-eat_separator (st_parameter_dt *dtp)
-{
- int c, n;
- int err = 0;
-
- eat_spaces (dtp);
- dtp->u.p.comma_flag = 0;
-
- if ((c = next_char (dtp)) == EOF)
- return LIBERROR_END;
- switch (c)
- {
- case ',':
- if (dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
- {
- unget_char (dtp, c);
- break;
- }
- /* Fall through. */
- case ';':
- dtp->u.p.comma_flag = 1;
- eat_spaces (dtp);
- break;
-
- case '/':
- dtp->u.p.input_complete = 1;
- break;
-
- case '\r':
- dtp->u.p.at_eol = 1;
- if ((n = next_char(dtp)) == EOF)
- return LIBERROR_END;
- if (n != '\n')
- {
- unget_char (dtp, n);
- break;
- }
- /* Fall through. */
- case '\n':
- dtp->u.p.at_eol = 1;
- if (dtp->u.p.namelist_mode)
- {
- do
- {
- if ((c = next_char (dtp)) == EOF)
- return LIBERROR_END;
- if (c == '!')
- {
- err = eat_line (dtp);
- if (err)
- return err;
- c = '\n';
- }
- }
- while (c == '\n' || c == '\r' || c == ' ' || c == '\t');
- unget_char (dtp, c);
- }
- break;
-
- case '!':
- if (dtp->u.p.namelist_mode)
- { /* Eat a namelist comment. */
- err = eat_line (dtp);
- if (err)
- return err;
-
- break;
- }
-
- /* Fall Through... */
-
- default:
- unget_char (dtp, c);
- break;
- }
- return err;
-}
-
-
-/* Finish processing a separator that was interrupted by a newline.
- If we're here, then another data item is present, so we finish what
- we started on the previous line. Return 0 on success, error code
- on failure. */
-
-static int
-finish_separator (st_parameter_dt *dtp)
-{
- int c;
- int err;
-
- restart:
- eat_spaces (dtp);
-
- if ((c = next_char (dtp)) == EOF)
- return LIBERROR_END;
- switch (c)
- {
- case ',':
- if (dtp->u.p.comma_flag)
- unget_char (dtp, c);
- else
- {
- if ((c = eat_spaces (dtp)) == EOF)
- return LIBERROR_END;
- if (c == '\n' || c == '\r')
- goto restart;
- }
-
- break;
-
- case '/':
- dtp->u.p.input_complete = 1;
- if (!dtp->u.p.namelist_mode)
- return err;
- break;
-
- case '\n':
- case '\r':
- goto restart;
-
- case '!':
- if (dtp->u.p.namelist_mode)
- {
- err = eat_line (dtp);
- if (err)
- return err;
- goto restart;
- }
-
- default:
- unget_char (dtp, c);
- break;
- }
- return err;
-}
-
-
-/* This function is needed to catch bad conversions so that namelist can
- attempt to see if dtp->u.p.saved_string contains a new object name rather
- than a bad value. */
-
-static int
-nml_bad_return (st_parameter_dt *dtp, char c)
-{
- if (dtp->u.p.namelist_mode)
- {
- dtp->u.p.nml_read_error = 1;
- unget_char (dtp, c);
- return 1;
- }
- return 0;
-}
-
-/* Convert an unsigned string to an integer. The length value is -1
- if we are working on a repeat count. Returns nonzero if we have a
- range problem. As a side effect, frees the dtp->u.p.saved_string. */
-
-static int
-convert_integer (st_parameter_dt *dtp, int length, int negative)
-{
- char c, *buffer, message[MSGLEN];
- int m;
- GFC_UINTEGER_LARGEST v, max, max10;
- GFC_INTEGER_LARGEST value;
-
- buffer = dtp->u.p.saved_string;
- v = 0;
-
- if (length == -1)
- max = MAX_REPEAT;
- else
- {
- max = si_max (length);
- if (negative)
- max++;
- }
- max10 = max / 10;
-
- for (;;)
- {
- c = *buffer++;
- if (c == '\0')
- break;
- c -= '0';
-
- if (v > max10)
- goto overflow;
- v = 10 * v;
-
- if (v > max - c)
- goto overflow;
- v += c;
- }
-
- m = 0;
-
- if (length != -1)
- {
- if (negative)
- value = -v;
- else
- value = v;
- set_integer (dtp->u.p.value, value, length);
- }
- else
- {
- dtp->u.p.repeat_count = v;
-
- if (dtp->u.p.repeat_count == 0)
- {
- snprintf (message, MSGLEN, "Zero repeat count in item %d of list input",
- dtp->u.p.item_count);
-
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
- m = 1;
- }
- }
-
- free_saved (dtp);
- return m;
-
- overflow:
- if (length == -1)
- snprintf (message, MSGLEN, "Repeat count overflow in item %d of list input",
- dtp->u.p.item_count);
- else
- snprintf (message, MSGLEN, "Integer overflow while reading item %d",
- dtp->u.p.item_count);
-
- free_saved (dtp);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
-
- return 1;
-}
-
-
-/* Parse a repeat count for logical and complex values which cannot
- begin with a digit. Returns nonzero if we are done, zero if we
- should continue on. */
-
-static int
-parse_repeat (st_parameter_dt *dtp)
-{
- char message[MSGLEN];
- int c, repeat;
-
- if ((c = next_char (dtp)) == EOF)
- goto bad_repeat;
- switch (c)
- {
- CASE_DIGITS:
- repeat = c - '0';
- break;
-
- CASE_SEPARATORS:
- unget_char (dtp, c);
- eat_separator (dtp);
- return 1;
-
- default:
- unget_char (dtp, c);
- return 0;
- }
-
- for (;;)
- {
- c = next_char (dtp);
- switch (c)
- {
- CASE_DIGITS:
- repeat = 10 * repeat + c - '0';
-
- if (repeat > MAX_REPEAT)
- {
- snprintf (message, MSGLEN,
- "Repeat count overflow in item %d of list input",
- dtp->u.p.item_count);
-
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
- return 1;
- }
-
- break;
-
- case '*':
- if (repeat == 0)
- {
- snprintf (message, MSGLEN,
- "Zero repeat count in item %d of list input",
- dtp->u.p.item_count);
-
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
- return 1;
- }
-
- goto done;
-
- default:
- goto bad_repeat;
- }
- }
-
- done:
- dtp->u.p.repeat_count = repeat;
- return 0;
-
- bad_repeat:
-
- free_saved (dtp);
- if (c == EOF)
- {
- hit_eof (dtp);
- return 1;
- }
- else
- eat_line (dtp);
- snprintf (message, MSGLEN, "Bad repeat count in item %d of list input",
- dtp->u.p.item_count);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
- return 1;
-}
-
-
-/* To read a logical we have to look ahead in the input stream to make sure
- there is not an equal sign indicating a variable name. To do this we use
- line_buffer to point to a temporary buffer, pushing characters there for
- possible later reading. */
-
-static void
-l_push_char (st_parameter_dt *dtp, char c)
-{
- if (dtp->u.p.line_buffer == NULL)
- dtp->u.p.line_buffer = xcalloc (SCRATCH_SIZE, 1);
-
- dtp->u.p.line_buffer[dtp->u.p.item_count++] = c;
-}
-
-
-/* Read a logical character on the input. */
-
-static void
-read_logical (st_parameter_dt *dtp, int length)
-{
- char message[MSGLEN];
- int c, i, v;
-
- if (parse_repeat (dtp))
- return;
-
- c = tolower (next_char (dtp));
- l_push_char (dtp, c);
- switch (c)
- {
- case 't':
- v = 1;
- c = next_char (dtp);
- l_push_char (dtp, c);
-
- if (!is_separator(c) && c != EOF)
- goto possible_name;
-
- unget_char (dtp, c);
- break;
- case 'f':
- v = 0;
- c = next_char (dtp);
- l_push_char (dtp, c);
-
- if (!is_separator(c) && c != EOF)
- goto possible_name;
-
- unget_char (dtp, c);
- break;
-
- case '.':
- c = tolower (next_char (dtp));
- switch (c)
- {
- case 't':
- v = 1;
- break;
- case 'f':
- v = 0;
- break;
- default:
- goto bad_logical;
- }
-
- break;
-
- CASE_SEPARATORS:
- case EOF:
- unget_char (dtp, c);
- eat_separator (dtp);
- return; /* Null value. */
-
- default:
- /* Save the character in case it is the beginning
- of the next object name. */
- unget_char (dtp, c);
- goto bad_logical;
- }
-
- dtp->u.p.saved_type = BT_LOGICAL;
- dtp->u.p.saved_length = length;
-
- /* Eat trailing garbage. */
- do
- c = next_char (dtp);
- while (c != EOF && !is_separator (c));
-
- unget_char (dtp, c);
- eat_separator (dtp);
- set_integer ((int *) dtp->u.p.value, v, length);
- free_line (dtp);
-
- return;
-
- possible_name:
-
- for(i = 0; i < 63; i++)
- {
- c = next_char (dtp);
- if (is_separator(c))
- {
- /* All done if this is not a namelist read. */
- if (!dtp->u.p.namelist_mode)
- goto logical_done;
-
- unget_char (dtp, c);
- eat_separator (dtp);
- c = next_char (dtp);
- if (c != '=')
- {
- unget_char (dtp, c);
- goto logical_done;
- }
- }
-
- l_push_char (dtp, c);
- if (c == '=')
- {
- dtp->u.p.nml_read_error = 1;
- dtp->u.p.line_buffer_enabled = 1;
- dtp->u.p.item_count = 0;
- return;
- }
-
- }
-
- bad_logical:
-
- free_line (dtp);
-
- if (nml_bad_return (dtp, c))
- return;
-
- free_saved (dtp);
- if (c == EOF)
- {
- hit_eof (dtp);
- return;
- }
- else if (c != '\n')
- eat_line (dtp);
- snprintf (message, MSGLEN, "Bad logical value while reading item %d",
- dtp->u.p.item_count);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
- return;
-
- logical_done:
-
- dtp->u.p.saved_type = BT_LOGICAL;
- dtp->u.p.saved_length = length;
- set_integer ((int *) dtp->u.p.value, v, length);
- free_saved (dtp);
- free_line (dtp);
-}
-
-
-/* Reading integers is tricky because we can actually be reading a
- repeat count. We have to store the characters in a buffer because
- we could be reading an integer that is larger than the default int
- used for repeat counts. */
-
-static void
-read_integer (st_parameter_dt *dtp, int length)
-{
- char message[MSGLEN];
- int c, negative;
-
- negative = 0;
-
- c = next_char (dtp);
- switch (c)
- {
- case '-':
- negative = 1;
- /* Fall through... */
-
- case '+':
- if ((c = next_char (dtp)) == EOF)
- goto bad_integer;
- goto get_integer;
-
- CASE_SEPARATORS: /* Single null. */
- unget_char (dtp, c);
- eat_separator (dtp);
- return;
-
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- default:
- goto bad_integer;
- }
-
- /* Take care of what may be a repeat count. */
-
- for (;;)
- {
- c = next_char (dtp);
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- case '*':
- push_char (dtp, '\0');
- goto repeat;
-
- CASE_SEPARATORS: /* Not a repeat count. */
- case EOF:
- goto done;
-
- default:
- goto bad_integer;
- }
- }
-
- repeat:
- if (convert_integer (dtp, -1, 0))
- return;
-
- /* Get the real integer. */
-
- if ((c = next_char (dtp)) == EOF)
- goto bad_integer;
- switch (c)
- {
- CASE_DIGITS:
- break;
-
- CASE_SEPARATORS:
- unget_char (dtp, c);
- eat_separator (dtp);
- return;
-
- case '-':
- negative = 1;
- /* Fall through... */
-
- case '+':
- c = next_char (dtp);
- break;
- }
-
- get_integer:
- if (!isdigit (c))
- goto bad_integer;
- push_char (dtp, c);
-
- for (;;)
- {
- c = next_char (dtp);
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- CASE_SEPARATORS:
- case EOF:
- goto done;
-
- default:
- goto bad_integer;
- }
- }
-
- bad_integer:
-
- if (nml_bad_return (dtp, c))
- return;
-
- free_saved (dtp);
- if (c == EOF)
- {
- hit_eof (dtp);
- return;
- }
- else if (c != '\n')
- eat_line (dtp);
- snprintf (message, MSGLEN, "Bad integer for item %d in list input",
- dtp->u.p.item_count);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
-
- return;
-
- done:
- unget_char (dtp, c);
- eat_separator (dtp);
-
- push_char (dtp, '\0');
- if (convert_integer (dtp, length, negative))
- {
- free_saved (dtp);
- return;
- }
-
- free_saved (dtp);
- dtp->u.p.saved_type = BT_INTEGER;
-}
-
-
-/* Read a character variable. */
-
-static void
-read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
-{
- char quote, message[MSGLEN];
- int c;
-
- quote = ' '; /* Space means no quote character. */
-
- if ((c = next_char (dtp)) == EOF)
- goto eof;
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- CASE_SEPARATORS:
- case EOF:
- unget_char (dtp, c); /* NULL value. */
- eat_separator (dtp);
- return;
-
- case '"':
- case '\'':
- quote = c;
- goto get_string;
-
- default:
- if (dtp->u.p.namelist_mode)
- {
- unget_char (dtp, c);
- return;
- }
-
- push_char (dtp, c);
- goto get_string;
- }
-
- /* Deal with a possible repeat count. */
-
- for (;;)
- {
- c = next_char (dtp);
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- CASE_SEPARATORS:
- case EOF:
- unget_char (dtp, c);
- goto done; /* String was only digits! */
-
- case '*':
- push_char (dtp, '\0');
- goto got_repeat;
-
- default:
- push_char (dtp, c);
- goto get_string; /* Not a repeat count after all. */
- }
- }
-
- got_repeat:
- if (convert_integer (dtp, -1, 0))
- return;
-
- /* Now get the real string. */
-
- if ((c = next_char (dtp)) == EOF)
- goto eof;
- switch (c)
- {
- CASE_SEPARATORS:
- unget_char (dtp, c); /* Repeated NULL values. */
- eat_separator (dtp);
- return;
-
- case '"':
- case '\'':
- quote = c;
- break;
-
- default:
- push_char (dtp, c);
- break;
- }
-
- get_string:
- for (;;)
- {
- if ((c = next_char (dtp)) == EOF)
- goto done_eof;
- switch (c)
- {
- case '"':
- case '\'':
- if (c != quote)
- {
- push_char (dtp, c);
- break;
- }
-
- /* See if we have a doubled quote character or the end of
- the string. */
-
- if ((c = next_char (dtp)) == EOF)
- goto done_eof;
- if (c == quote)
- {
- push_char (dtp, quote);
- break;
- }
-
- unget_char (dtp, c);
- goto done;
-
- CASE_SEPARATORS:
- if (quote == ' ')
- {
- unget_char (dtp, c);
- goto done;
- }
-
- if (c != '\n' && c != '\r')
- push_char (dtp, c);
- break;
-
- default:
- push_char (dtp, c);
- break;
- }
- }
-
- /* At this point, we have to have a separator, or else the string is
- invalid. */
- done:
- c = next_char (dtp);
- done_eof:
- if (is_separator (c) || c == '!' || c == EOF)
- {
- unget_char (dtp, c);
- eat_separator (dtp);
- dtp->u.p.saved_type = BT_CHARACTER;
- free_line (dtp);
- }
- else
- {
- free_saved (dtp);
- snprintf (message, MSGLEN, "Invalid string input in item %d",
- dtp->u.p.item_count);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
- }
- return;
-
- eof:
- free_saved (dtp);
- hit_eof (dtp);
-}
-
-
-/* Parse a component of a complex constant or a real number that we
- are sure is already there. This is a straight real number parser. */
-
-static int
-parse_real (st_parameter_dt *dtp, void *buffer, int length)
-{
- char message[MSGLEN];
- int c, m, seen_dp;
-
- if ((c = next_char (dtp)) == EOF)
- goto bad;
-
- if (c == '-' || c == '+')
- {
- push_char (dtp, c);
- if ((c = next_char (dtp)) == EOF)
- goto bad;
- }
-
- if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
- c = '.';
-
- if (!isdigit (c) && c != '.')
- {
- if (c == 'i' || c == 'I' || c == 'n' || c == 'N')
- goto inf_nan;
- else
- goto bad;
- }
-
- push_char (dtp, c);
-
- seen_dp = (c == '.') ? 1 : 0;
-
- for (;;)
- {
- if ((c = next_char (dtp)) == EOF)
- goto bad;
- if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
- c = '.';
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- case '.':
- if (seen_dp)
- goto bad;
-
- seen_dp = 1;
- push_char (dtp, c);
- break;
-
- case 'e':
- case 'E':
- case 'd':
- case 'D':
- case 'q':
- case 'Q':
- push_char (dtp, 'e');
- goto exp1;
-
- case '-':
- case '+':
- push_char (dtp, 'e');
- push_char (dtp, c);
- if ((c = next_char (dtp)) == EOF)
- goto bad;
- goto exp2;
-
- CASE_SEPARATORS:
- case EOF:
- goto done;
-
- default:
- goto done;
- }
- }
-
- exp1:
- if ((c = next_char (dtp)) == EOF)
- goto bad;
- if (c != '-' && c != '+')
- push_char (dtp, '+');
- else
- {
- push_char (dtp, c);
- c = next_char (dtp);
- }
-
- exp2:
- if (!isdigit (c))
- goto bad;
-
- push_char (dtp, c);
-
- for (;;)
- {
- if ((c = next_char (dtp)) == EOF)
- goto bad;
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- CASE_SEPARATORS:
- case EOF:
- unget_char (dtp, c);
- goto done;
-
- default:
- goto done;
- }
- }
-
- done:
- unget_char (dtp, c);
- push_char (dtp, '\0');
-
- m = convert_real (dtp, buffer, dtp->u.p.saved_string, length);
- free_saved (dtp);
-
- return m;
-
- done_infnan:
- unget_char (dtp, c);
- push_char (dtp, '\0');
-
- m = convert_infnan (dtp, buffer, dtp->u.p.saved_string, length);
- free_saved (dtp);
-
- return m;
-
- inf_nan:
- /* Match INF and Infinity. */
- if ((c == 'i' || c == 'I')
- && ((c = next_char (dtp)) == 'n' || c == 'N')
- && ((c = next_char (dtp)) == 'f' || c == 'F'))
- {
- c = next_char (dtp);
- if ((c != 'i' && c != 'I')
- || ((c == 'i' || c == 'I')
- && ((c = next_char (dtp)) == 'n' || c == 'N')
- && ((c = next_char (dtp)) == 'i' || c == 'I')
- && ((c = next_char (dtp)) == 't' || c == 'T')
- && ((c = next_char (dtp)) == 'y' || c == 'Y')
- && (c = next_char (dtp))))
- {
- if (is_separator (c) || (c == EOF))
- unget_char (dtp, c);
- push_char (dtp, 'i');
- push_char (dtp, 'n');
- push_char (dtp, 'f');
- goto done_infnan;
- }
- } /* Match NaN. */
- else if (((c = next_char (dtp)) == 'a' || c == 'A')
- && ((c = next_char (dtp)) == 'n' || c == 'N')
- && (c = next_char (dtp)))
- {
- if (is_separator (c) || (c == EOF))
- unget_char (dtp, c);
- push_char (dtp, 'n');
- push_char (dtp, 'a');
- push_char (dtp, 'n');
-
- /* Match "NAN(alphanum)". */
- if (c == '(')
- {
- for ( ; c != ')'; c = next_char (dtp))
- if (is_separator (c))
- goto bad;
-
- c = next_char (dtp);
- if (is_separator (c) || (c == EOF))
- unget_char (dtp, c);
- }
- goto done_infnan;
- }
-
- bad:
-
- if (nml_bad_return (dtp, c))
- return 0;
-
- free_saved (dtp);
- if (c == EOF)
- {
- hit_eof (dtp);
- return 1;
- }
- else if (c != '\n')
- eat_line (dtp);
- snprintf (message, MSGLEN, "Bad floating point number for item %d",
- dtp->u.p.item_count);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
-
- return 1;
-}
-
-
-/* Reading a complex number is straightforward because we can tell
- what it is right away. */
-
-static void
-read_complex (st_parameter_dt *dtp, void * dest, int kind, size_t size)
-{
- char message[MSGLEN];
- int c;
-
- if (parse_repeat (dtp))
- return;
-
- c = next_char (dtp);
- switch (c)
- {
- case '(':
- break;
-
- CASE_SEPARATORS:
- case EOF:
- unget_char (dtp, c);
- eat_separator (dtp);
- return;
-
- default:
- goto bad_complex;
- }
-
-eol_1:
- eat_spaces (dtp);
- c = next_char (dtp);
- if (c == '\n' || c== '\r')
- goto eol_1;
- else
- unget_char (dtp, c);
-
- if (parse_real (dtp, dest, kind))
- return;
-
-eol_2:
- eat_spaces (dtp);
- c = next_char (dtp);
- if (c == '\n' || c== '\r')
- goto eol_2;
- else
- unget_char (dtp, c);
-
- if (next_char (dtp)
- != (dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';'))
- goto bad_complex;
-
-eol_3:
- eat_spaces (dtp);
- c = next_char (dtp);
- if (c == '\n' || c== '\r')
- goto eol_3;
- else
- unget_char (dtp, c);
-
- if (parse_real (dtp, dest + size / 2, kind))
- return;
-
-eol_4:
- eat_spaces (dtp);
- c = next_char (dtp);
- if (c == '\n' || c== '\r')
- goto eol_4;
- else
- unget_char (dtp, c);
-
- if (next_char (dtp) != ')')
- goto bad_complex;
-
- c = next_char (dtp);
- if (!is_separator (c) && (c != EOF))
- goto bad_complex;
-
- unget_char (dtp, c);
- eat_separator (dtp);
-
- free_saved (dtp);
- dtp->u.p.saved_type = BT_COMPLEX;
- return;
-
- bad_complex:
-
- if (nml_bad_return (dtp, c))
- return;
-
- free_saved (dtp);
- if (c == EOF)
- {
- hit_eof (dtp);
- return;
- }
- else if (c != '\n')
- eat_line (dtp);
- snprintf (message, MSGLEN, "Bad complex value in item %d of list input",
- dtp->u.p.item_count);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
-}
-
-
-/* Parse a real number with a possible repeat count. */
-
-static void
-read_real (st_parameter_dt *dtp, void * dest, int length)
-{
- char message[MSGLEN];
- int c;
- int seen_dp;
- int is_inf;
-
- seen_dp = 0;
-
- c = next_char (dtp);
- if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
- c = '.';
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- case '.':
- push_char (dtp, c);
- seen_dp = 1;
- break;
-
- case '+':
- case '-':
- goto got_sign;
-
- CASE_SEPARATORS:
- unget_char (dtp, c); /* Single null. */
- eat_separator (dtp);
- return;
-
- case 'i':
- case 'I':
- case 'n':
- case 'N':
- goto inf_nan;
-
- default:
- goto bad_real;
- }
-
- /* Get the digit string that might be a repeat count. */
-
- for (;;)
- {
- c = next_char (dtp);
- if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
- c = '.';
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- case '.':
- if (seen_dp)
- goto bad_real;
-
- seen_dp = 1;
- push_char (dtp, c);
- goto real_loop;
-
- case 'E':
- case 'e':
- case 'D':
- case 'd':
- case 'Q':
- case 'q':
- goto exp1;
-
- case '+':
- case '-':
- push_char (dtp, 'e');
- push_char (dtp, c);
- c = next_char (dtp);
- goto exp2;
-
- case '*':
- push_char (dtp, '\0');
- goto got_repeat;
-
- CASE_SEPARATORS:
- case EOF:
- if (c != '\n' && c != ',' && c != '\r' && c != ';')
- unget_char (dtp, c);
- goto done;
-
- default:
- goto bad_real;
- }
- }
-
- got_repeat:
- if (convert_integer (dtp, -1, 0))
- return;
-
- /* Now get the number itself. */
-
- if ((c = next_char (dtp)) == EOF)
- goto bad_real;
- if (is_separator (c))
- { /* Repeated null value. */
- unget_char (dtp, c);
- eat_separator (dtp);
- return;
- }
-
- if (c != '-' && c != '+')
- push_char (dtp, '+');
- else
- {
- got_sign:
- push_char (dtp, c);
- if ((c = next_char (dtp)) == EOF)
- goto bad_real;
- }
-
- if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
- c = '.';
-
- if (!isdigit (c) && c != '.')
- {
- if (c == 'i' || c == 'I' || c == 'n' || c == 'N')
- goto inf_nan;
- else
- goto bad_real;
- }
-
- if (c == '.')
- {
- if (seen_dp)
- goto bad_real;
- else
- seen_dp = 1;
- }
-
- push_char (dtp, c);
-
- real_loop:
- for (;;)
- {
- c = next_char (dtp);
- if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
- c = '.';
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- CASE_SEPARATORS:
- case EOF:
- goto done;
-
- case '.':
- if (seen_dp)
- goto bad_real;
-
- seen_dp = 1;
- push_char (dtp, c);
- break;
-
- case 'E':
- case 'e':
- case 'D':
- case 'd':
- case 'Q':
- case 'q':
- goto exp1;
-
- case '+':
- case '-':
- push_char (dtp, 'e');
- push_char (dtp, c);
- c = next_char (dtp);
- goto exp2;
-
- default:
- goto bad_real;
- }
- }
-
- exp1:
- push_char (dtp, 'e');
-
- if ((c = next_char (dtp)) == EOF)
- goto bad_real;
- if (c != '+' && c != '-')
- push_char (dtp, '+');
- else
- {
- push_char (dtp, c);
- c = next_char (dtp);
- }
-
- exp2:
- if (!isdigit (c))
- goto bad_real;
- push_char (dtp, c);
-
- for (;;)
- {
- c = next_char (dtp);
-
- switch (c)
- {
- CASE_DIGITS:
- push_char (dtp, c);
- break;
-
- CASE_SEPARATORS:
- case EOF:
- goto done;
-
- default:
- goto bad_real;
- }
- }
-
- done:
- unget_char (dtp, c);
- eat_separator (dtp);
- push_char (dtp, '\0');
- if (convert_real (dtp, dest, dtp->u.p.saved_string, length))
- return;
-
- free_saved (dtp);
- dtp->u.p.saved_type = BT_REAL;
- return;
-
- inf_nan:
- l_push_char (dtp, c);
- is_inf = 0;
-
- /* Match INF and Infinity. */
- if (c == 'i' || c == 'I')
- {
- c = next_char (dtp);
- l_push_char (dtp, c);
- if (c != 'n' && c != 'N')
- goto unwind;
- c = next_char (dtp);
- l_push_char (dtp, c);
- if (c != 'f' && c != 'F')
- goto unwind;
- c = next_char (dtp);
- l_push_char (dtp, c);
- if (!is_separator (c) && (c != EOF))
- {
- if (c != 'i' && c != 'I')
- goto unwind;
- c = next_char (dtp);
- l_push_char (dtp, c);
- if (c != 'n' && c != 'N')
- goto unwind;
- c = next_char (dtp);
- l_push_char (dtp, c);
- if (c != 'i' && c != 'I')
- goto unwind;
- c = next_char (dtp);
- l_push_char (dtp, c);
- if (c != 't' && c != 'T')
- goto unwind;
- c = next_char (dtp);
- l_push_char (dtp, c);
- if (c != 'y' && c != 'Y')
- goto unwind;
- c = next_char (dtp);
- l_push_char (dtp, c);
- }
- is_inf = 1;
- } /* Match NaN. */
- else
- {
- c = next_char (dtp);
- l_push_char (dtp, c);
- if (c != 'a' && c != 'A')
- goto unwind;
- c = next_char (dtp);
- l_push_char (dtp, c);
- if (c != 'n' && c != 'N')
- goto unwind;
- c = next_char (dtp);
- l_push_char (dtp, c);
-
- /* Match NAN(alphanum). */
- if (c == '(')
- {
- for (c = next_char (dtp); c != ')'; c = next_char (dtp))
- if (is_separator (c))
- goto unwind;
- else
- l_push_char (dtp, c);
-
- l_push_char (dtp, ')');
- c = next_char (dtp);
- l_push_char (dtp, c);
- }
- }
-
- if (!is_separator (c) && (c != EOF))
- goto unwind;
-
- if (dtp->u.p.namelist_mode)
- {
- if (c == ' ' || c =='\n' || c == '\r')
- {
- do
- {
- if ((c = next_char (dtp)) == EOF)
- goto bad_real;
- }
- while (c == ' ' || c =='\n' || c == '\r');
-
- l_push_char (dtp, c);
-
- if (c == '=')
- goto unwind;
- }
- }
-
- if (is_inf)
- {
- push_char (dtp, 'i');
- push_char (dtp, 'n');
- push_char (dtp, 'f');
- }
- else
- {
- push_char (dtp, 'n');
- push_char (dtp, 'a');
- push_char (dtp, 'n');
- }
-
- free_line (dtp);
- unget_char (dtp, c);
- eat_separator (dtp);
- push_char (dtp, '\0');
- if (convert_infnan (dtp, dest, dtp->u.p.saved_string, length))
- return;
-
- free_saved (dtp);
- dtp->u.p.saved_type = BT_REAL;
- return;
-
- unwind:
- if (dtp->u.p.namelist_mode)
- {
- dtp->u.p.nml_read_error = 1;
- dtp->u.p.line_buffer_enabled = 1;
- dtp->u.p.item_count = 0;
- return;
- }
-
- bad_real:
-
- if (nml_bad_return (dtp, c))
- return;
-
- free_saved (dtp);
- if (c == EOF)
- {
- hit_eof (dtp);
- return;
- }
- else if (c != '\n')
- eat_line (dtp);
-
- snprintf (message, MSGLEN, "Bad real number in item %d of list input",
- dtp->u.p.item_count);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
-}
-
-
-/* Check the current type against the saved type to make sure they are
- compatible. Returns nonzero if incompatible. */
-
-static int
-check_type (st_parameter_dt *dtp, bt type, int len)
-{
- char message[MSGLEN];
-
- if (dtp->u.p.saved_type != BT_UNKNOWN && dtp->u.p.saved_type != type)
- {
- snprintf (message, MSGLEN, "Read type %s where %s was expected for item %d",
- type_name (dtp->u.p.saved_type), type_name (type),
- dtp->u.p.item_count);
-
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
- return 1;
- }
-
- if (dtp->u.p.saved_type == BT_UNKNOWN || dtp->u.p.saved_type == BT_CHARACTER)
- return 0;
-
- if (dtp->u.p.saved_length != len)
- {
- snprintf (message, MSGLEN,
- "Read kind %d %s where kind %d is required for item %d",
- dtp->u.p.saved_length, type_name (dtp->u.p.saved_type), len,
- dtp->u.p.item_count);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
- return 1;
- }
-
- return 0;
-}
-
-
-/* Top level data transfer subroutine for list reads. Because we have
- to deal with repeat counts, the data item is always saved after
- reading, usually in the dtp->u.p.value[] array. If a repeat count is
- greater than one, we copy the data item multiple times. */
-
-static int
-list_formatted_read_scalar (st_parameter_dt *dtp, bt type, void *p,
- int kind, size_t size)
-{
- gfc_char4_t *q;
- int c, i, m;
- int err = 0;
-
- dtp->u.p.namelist_mode = 0;
-
- if (dtp->u.p.first_item)
- {
- dtp->u.p.first_item = 0;
- dtp->u.p.input_complete = 0;
- dtp->u.p.repeat_count = 1;
- dtp->u.p.at_eol = 0;
-
- if ((c = eat_spaces (dtp)) == EOF)
- {
- err = LIBERROR_END;
- goto cleanup;
- }
- if (is_separator (c))
- {
- /* Found a null value. */
- eat_separator (dtp);
- dtp->u.p.repeat_count = 0;
-
- /* eat_separator sets this flag if the separator was a comma. */
- if (dtp->u.p.comma_flag)
- goto cleanup;
-
- /* eat_separator sets this flag if the separator was a \n or \r. */
- if (dtp->u.p.at_eol)
- finish_separator (dtp);
- else
- goto cleanup;
- }
-
- }
- else
- {
- if (dtp->u.p.repeat_count > 0)
- {
- if (check_type (dtp, type, kind))
- return err;
- goto set_value;
- }
-
- if (dtp->u.p.input_complete)
- goto cleanup;
-
- if (dtp->u.p.at_eol)
- finish_separator (dtp);
- else
- {
- eat_spaces (dtp);
- /* Trailing spaces prior to end of line. */
- if (dtp->u.p.at_eol)
- finish_separator (dtp);
- }
-
- dtp->u.p.saved_type = BT_UNKNOWN;
- dtp->u.p.repeat_count = 1;
- }
-
- switch (type)
- {
- case BT_INTEGER:
- read_integer (dtp, kind);
- break;
- case BT_LOGICAL:
- read_logical (dtp, kind);
- break;
- case BT_CHARACTER:
- read_character (dtp, kind);
- break;
- case BT_REAL:
- read_real (dtp, p, kind);
- /* Copy value back to temporary if needed. */
- if (dtp->u.p.repeat_count > 0)
- memcpy (dtp->u.p.value, p, size);
- break;
- case BT_COMPLEX:
- read_complex (dtp, p, kind, size);
- /* Copy value back to temporary if needed. */
- if (dtp->u.p.repeat_count > 0)
- memcpy (dtp->u.p.value, p, size);
- break;
- default:
- internal_error (&dtp->common, "Bad type for list read");
- }
-
- if (dtp->u.p.saved_type != BT_CHARACTER && dtp->u.p.saved_type != BT_UNKNOWN)
- dtp->u.p.saved_length = size;
-
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- goto cleanup;
-
- set_value:
- switch (dtp->u.p.saved_type)
- {
- case BT_COMPLEX:
- case BT_REAL:
- if (dtp->u.p.repeat_count > 0)
- memcpy (p, dtp->u.p.value, size);
- break;
-
- case BT_INTEGER:
- case BT_LOGICAL:
- memcpy (p, dtp->u.p.value, size);
- break;
-
- case BT_CHARACTER:
- if (dtp->u.p.saved_string)
- {
- m = ((int) size < dtp->u.p.saved_used)
- ? (int) size : dtp->u.p.saved_used;
- if (kind == 1)
- memcpy (p, dtp->u.p.saved_string, m);
- else
- {
- q = (gfc_char4_t *) p;
- for (i = 0; i < m; i++)
- q[i] = (unsigned char) dtp->u.p.saved_string[i];
- }
- }
- else
- /* Just delimiters encountered, nothing to copy but SPACE. */
- m = 0;
-
- if (m < (int) size)
- {
- if (kind == 1)
- memset (((char *) p) + m, ' ', size - m);
- else
- {
- q = (gfc_char4_t *) p;
- for (i = m; i < (int) size; i++)
- q[i] = (unsigned char) ' ';
- }
- }
- break;
-
- case BT_UNKNOWN:
- break;
-
- default:
- internal_error (&dtp->common, "Bad type for list read");
- }
-
- if (--dtp->u.p.repeat_count <= 0)
- free_saved (dtp);
-
-cleanup:
- if (err == LIBERROR_END)
- hit_eof (dtp);
- return err;
-}
-
-
-void
-list_formatted_read (st_parameter_dt *dtp, bt type, void *p, int kind,
- size_t size, size_t nelems)
-{
- size_t elem;
- char *tmp;
- size_t stride = type == BT_CHARACTER ?
- size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
- int err;
-
- tmp = (char *) p;
-
- /* Big loop over all the elements. */
- for (elem = 0; elem < nelems; elem++)
- {
- dtp->u.p.item_count++;
- err = list_formatted_read_scalar (dtp, type, tmp + stride*elem,
- kind, size);
- if (err)
- break;
- }
-}
-
-
-/* Finish a list read. */
-
-void
-finish_list_read (st_parameter_dt *dtp)
-{
- int err;
-
- 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;
- return;
- }
-
- err = eat_line (dtp);
- if (err == LIBERROR_END)
- hit_eof (dtp);
-}
-
-/* NAMELIST INPUT
-
-void namelist_read (st_parameter_dt *dtp)
-calls:
- static void nml_match_name (char *name, int len)
- static int nml_query (st_parameter_dt *dtp)
- static int nml_get_obj_data (st_parameter_dt *dtp,
- namelist_info **prev_nl, char *, size_t)
-calls:
- static void nml_untouch_nodes (st_parameter_dt *dtp)
- static namelist_info * find_nml_node (st_parameter_dt *dtp,
- char * var_name)
- static int nml_parse_qualifier(descriptor_dimension * ad,
- array_loop_spec * ls, int rank, char *)
- static void nml_touch_nodes (namelist_info * nl)
- static int nml_read_obj (namelist_info *nl, index_type offset,
- namelist_info **prev_nl, char *, size_t,
- index_type clow, index_type chigh)
-calls:
- -itself- */
-
-/* Inputs a rank-dimensional qualifier, which can contain
- singlets, doublets, triplets or ':' with the standard meanings. */
-
-static try
-nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
- array_loop_spec *ls, int rank, bt nml_elem_type,
- char *parse_err_msg, size_t parse_err_msg_size,
- int *parsed_rank)
-{
- int dim;
- int indx;
- int neg;
- int null_flag;
- int is_array_section, is_char;
- int c;
-
- is_char = 0;
- is_array_section = 0;
- dtp->u.p.expanded_read = 0;
-
- /* See if this is a character substring qualifier we are looking for. */
- if (rank == -1)
- {
- rank = 1;
- is_char = 1;
- }
-
- /* The next character in the stream should be the '('. */
-
- if ((c = next_char (dtp)) == EOF)
- goto err_ret;
-
- /* Process the qualifier, by dimension and triplet. */
-
- for (dim=0; dim < rank; dim++ )
- {
- for (indx=0; indx<3; indx++)
- {
- free_saved (dtp);
- eat_spaces (dtp);
- neg = 0;
-
- /* Process a potential sign. */
- if ((c = next_char (dtp)) == EOF)
- goto err_ret;
- switch (c)
- {
- case '-':
- neg = 1;
- break;
-
- case '+':
- break;
-
- default:
- unget_char (dtp, c);
- break;
- }
-
- /* Process characters up to the next ':' , ',' or ')'. */
- for (;;)
- {
- c = next_char (dtp);
- switch (c)
- {
- case EOF:
- goto err_ret;
-
- case ':':
- is_array_section = 1;
- break;
-
- case ',': case ')':
- if ((c==',' && dim == rank -1)
- || (c==')' && dim < rank -1))
- {
- if (is_char)
- snprintf (parse_err_msg, parse_err_msg_size,
- "Bad substring qualifier");
- else
- snprintf (parse_err_msg, parse_err_msg_size,
- "Bad number of index fields");
- goto err_ret;
- }
- break;
-
- CASE_DIGITS:
- push_char (dtp, c);
- continue;
-
- case ' ': case '\t': case '\r': case '\n':
- eat_spaces (dtp);
- break;
-
- default:
- if (is_char)
- snprintf (parse_err_msg, parse_err_msg_size,
- "Bad character in substring qualifier");
- else
- snprintf (parse_err_msg, parse_err_msg_size,
- "Bad character in index");
- goto err_ret;
- }
-
- if ((c == ',' || c == ')') && indx == 0
- && dtp->u.p.saved_string == 0)
- {
- if (is_char)
- snprintf (parse_err_msg, parse_err_msg_size,
- "Null substring qualifier");
- else
- snprintf (parse_err_msg, parse_err_msg_size,
- "Null index field");
- goto err_ret;
- }
-
- if ((c == ':' && indx == 1 && dtp->u.p.saved_string == 0)
- || (indx == 2 && dtp->u.p.saved_string == 0))
- {
- if (is_char)
- snprintf (parse_err_msg, parse_err_msg_size,
- "Bad substring qualifier");
- else
- snprintf (parse_err_msg, parse_err_msg_size,
- "Bad index triplet");
- goto err_ret;
- }
-
- if (is_char && !is_array_section)
- {
- snprintf (parse_err_msg, parse_err_msg_size,
- "Missing colon in substring qualifier");
- goto err_ret;
- }
-
- /* If '( : ? )' or '( ? : )' break and flag read failure. */
- null_flag = 0;
- if ((c == ':' && indx == 0 && dtp->u.p.saved_string == 0)
- || (indx==1 && dtp->u.p.saved_string == 0))
- {
- null_flag = 1;
- break;
- }
-
- /* Now read the index. */
- if (convert_integer (dtp, sizeof(index_type), neg))
- {
- if (is_char)
- snprintf (parse_err_msg, parse_err_msg_size,
- "Bad integer substring qualifier");
- else
- snprintf (parse_err_msg, parse_err_msg_size,
- "Bad integer in index");
- goto err_ret;
- }
- break;
- }
-
- /* Feed the index values to the triplet arrays. */
- if (!null_flag)
- {
- if (indx == 0)
- memcpy (&ls[dim].start, dtp->u.p.value, sizeof(index_type));
- if (indx == 1)
- memcpy (&ls[dim].end, dtp->u.p.value, sizeof(index_type));
- if (indx == 2)
- memcpy (&ls[dim].step, dtp->u.p.value, sizeof(index_type));
- }
-
- /* Singlet or doublet indices. */
- if (c==',' || c==')')
- {
- if (indx == 0)
- {
- memcpy (&ls[dim].start, dtp->u.p.value, sizeof(index_type));
-
- /* If -std=f95/2003 or an array section is specified,
- do not allow excess data to be processed. */
- if (is_array_section == 1
- || !(compile_options.allow_std & GFC_STD_GNU)
- || nml_elem_type == BT_DERIVED)
- ls[dim].end = ls[dim].start;
- else
- dtp->u.p.expanded_read = 1;
- }
-
- /* Check for non-zero rank. */
- if (is_array_section == 1 && ls[dim].start != ls[dim].end)
- *parsed_rank = 1;
-
- break;
- }
- }
-
- if (is_array_section == 1 && dtp->u.p.expanded_read == 1)
- {
- int i;
- dtp->u.p.expanded_read = 0;
- for (i = 0; i < dim; i++)
- ls[i].end = ls[i].start;
- }
-
- /* Check the values of the triplet indices. */
- if ((ls[dim].start > GFC_DIMENSION_UBOUND(ad[dim]))
- || (ls[dim].start < GFC_DIMENSION_LBOUND(ad[dim]))
- || (ls[dim].end > GFC_DIMENSION_UBOUND(ad[dim]))
- || (ls[dim].end < GFC_DIMENSION_LBOUND(ad[dim])))
- {
- if (is_char)
- snprintf (parse_err_msg, parse_err_msg_size,
- "Substring out of range");
- else
- snprintf (parse_err_msg, parse_err_msg_size,
- "Index %d out of range", dim + 1);
- goto err_ret;
- }
-
- if (((ls[dim].end - ls[dim].start ) * ls[dim].step < 0)
- || (ls[dim].step == 0))
- {
- snprintf (parse_err_msg, parse_err_msg_size,
- "Bad range in index %d", dim + 1);
- goto err_ret;
- }
-
- /* Initialise the loop index counter. */
- ls[dim].idx = ls[dim].start;
- }
- eat_spaces (dtp);
- return SUCCESS;
-
-err_ret:
-
- /* The EOF error message is issued by hit_eof. Return true so that the
- caller does not use parse_err_msg and parse_err_msg_size to generate
- an unrelated error message. */
- if (c == EOF)
- {
- hit_eof (dtp);
- dtp->u.p.input_complete = 1;
- return SUCCESS;
- }
- return FAILURE;
-}
-
-static namelist_info *
-find_nml_node (st_parameter_dt *dtp, char * var_name)
-{
- namelist_info * t = dtp->u.p.ionml;
- while (t != NULL)
- {
- if (strcmp (var_name, t->var_name) == 0)
- {
- t->touched = 1;
- return t;
- }
- t = t->next;
- }
- return NULL;
-}
-
-/* Visits all the components of a derived type that have
- not explicitly been identified in the namelist input.
- touched is set and the loop specification initialised
- to default values */
-
-static void
-nml_touch_nodes (namelist_info * nl)
-{
- index_type len = strlen (nl->var_name) + 1;
- int dim;
- char * ext_name = (char*)xmalloc (len + 1);
- memcpy (ext_name, nl->var_name, len-1);
- memcpy (ext_name + len - 1, "%", 2);
- for (nl = nl->next; nl; nl = nl->next)
- {
- if (strncmp (nl->var_name, ext_name, len) == 0)
- {
- nl->touched = 1;
- for (dim=0; dim < nl->var_rank; dim++)
- {
- nl->ls[dim].step = 1;
- nl->ls[dim].end = GFC_DESCRIPTOR_UBOUND(nl,dim);
- nl->ls[dim].start = GFC_DESCRIPTOR_LBOUND(nl,dim);
- nl->ls[dim].idx = nl->ls[dim].start;
- }
- }
- else
- break;
- }
- free (ext_name);
- return;
-}
-
-/* Resets touched for the entire list of nml_nodes, ready for a
- new object. */
-
-static void
-nml_untouch_nodes (st_parameter_dt *dtp)
-{
- namelist_info * t;
- for (t = dtp->u.p.ionml; t; t = t->next)
- t->touched = 0;
- return;
-}
-
-/* Attempts to input name to namelist name. Returns
- dtp->u.p.nml_read_error = 1 on no match. */
-
-static void
-nml_match_name (st_parameter_dt *dtp, const char *name, index_type len)
-{
- index_type i;
- int c;
-
- dtp->u.p.nml_read_error = 0;
- for (i = 0; i < len; i++)
- {
- c = next_char (dtp);
- if (c == EOF || (tolower (c) != tolower (name[i])))
- {
- dtp->u.p.nml_read_error = 1;
- break;
- }
- }
-}
-
-/* If the namelist read is from stdin, output the current state of the
- namelist to stdout. This is used to implement the non-standard query
- features, ? and =?. If c == '=' the full namelist is printed. Otherwise
- the names alone are printed. */
-
-static void
-nml_query (st_parameter_dt *dtp, char c)
-{
- gfc_unit * temp_unit;
- namelist_info * nl;
- index_type len;
- char * p;
-#ifdef HAVE_CRLF
- static const index_type endlen = 2;
- static const char endl[] = "\r\n";
- static const char nmlend[] = "&end\r\n";
-#else
- static const index_type endlen = 1;
- static const char endl[] = "\n";
- static const char nmlend[] = "&end\n";
-#endif
-
- if (dtp->u.p.current_unit->unit_number != options.stdin_unit)
- return;
-
- /* Store the current unit and transfer to stdout. */
-
- temp_unit = dtp->u.p.current_unit;
- dtp->u.p.current_unit = find_unit (options.stdout_unit);
-
- if (dtp->u.p.current_unit)
- {
- dtp->u.p.mode = WRITING;
- next_record (dtp, 0);
-
- /* Write the namelist in its entirety. */
-
- if (c == '=')
- namelist_write (dtp);
-
- /* Or write the list of names. */
-
- else
- {
- /* "&namelist_name\n" */
-
- len = dtp->namelist_name_len;
- p = write_block (dtp, len - 1 + endlen);
- if (!p)
- goto query_return;
- memcpy (p, "&", 1);
- memcpy ((char*)(p + 1), dtp->namelist_name, len);
- memcpy ((char*)(p + len + 1), &endl, endlen);
- for (nl = dtp->u.p.ionml; nl; nl = nl->next)
- {
- /* " var_name\n" */
-
- len = strlen (nl->var_name);
- p = write_block (dtp, len + endlen);
- if (!p)
- goto query_return;
- memcpy (p, " ", 1);
- memcpy ((char*)(p + 1), nl->var_name, len);
- memcpy ((char*)(p + len + 1), &endl, endlen);
- }
-
- /* "&end\n" */
-
- p = write_block (dtp, endlen + 4);
- if (!p)
- goto query_return;
- memcpy (p, &nmlend, endlen + 4);
- }
-
- /* Flush the stream to force immediate output. */
-
- fbuf_flush (dtp->u.p.current_unit, WRITING);
- sflush (dtp->u.p.current_unit->s);
- unlock_unit (dtp->u.p.current_unit);
- }
-
-query_return:
-
- /* Restore the current unit. */
-
- dtp->u.p.current_unit = temp_unit;
- dtp->u.p.mode = READING;
- return;
-}
-
-/* Reads and stores the input for the namelist object nl. For an array,
- the function loops over the ranges defined by the loop specification.
- This default to all the data or to the specification from a qualifier.
- nml_read_obj recursively calls itself to read derived types. It visits
- all its own components but only reads data for those that were touched
- when the name was parsed. If a read error is encountered, an attempt is
- made to return to read a new object name because the standard allows too
- little data to be available. On the other hand, too much data is an
- error. */
-
-static try
-nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset,
- namelist_info **pprev_nl, char *nml_err_msg,
- size_t nml_err_msg_size, index_type clow, index_type chigh)
-{
- namelist_info * cmp;
- char * obj_name;
- int nml_carry;
- int len;
- int dim;
- index_type dlen;
- index_type m;
- size_t obj_name_len;
- void * pdata;
-
- /* This object not touched in name parsing. */
-
- if (!nl->touched)
- return SUCCESS;
-
- dtp->u.p.repeat_count = 0;
- eat_spaces (dtp);
-
- len = nl->len;
- switch (nl->type)
- {
- case BT_INTEGER:
- case BT_LOGICAL:
- dlen = len;
- break;
-
- case BT_REAL:
- dlen = size_from_real_kind (len);
- break;
-
- case BT_COMPLEX:
- dlen = size_from_complex_kind (len);
- break;
-
- case BT_CHARACTER:
- dlen = chigh ? (chigh - clow + 1) : nl->string_length;
- break;
-
- default:
- dlen = 0;
- }
-
- do
- {
- /* Update the pointer to the data, using the current index vector */
-
- pdata = (void*)(nl->mem_pos + offset);
- for (dim = 0; dim < nl->var_rank; dim++)
- pdata = (void*)(pdata + (nl->ls[dim].idx
- - GFC_DESCRIPTOR_LBOUND(nl,dim))
- * GFC_DESCRIPTOR_STRIDE(nl,dim) * nl->size);
-
- /* Reset the error flag and try to read next value, if
- dtp->u.p.repeat_count=0 */
-
- dtp->u.p.nml_read_error = 0;
- nml_carry = 0;
- if (--dtp->u.p.repeat_count <= 0)
- {
- if (dtp->u.p.input_complete)
- return SUCCESS;
- if (dtp->u.p.at_eol)
- finish_separator (dtp);
- if (dtp->u.p.input_complete)
- return SUCCESS;
-
- dtp->u.p.saved_type = BT_UNKNOWN;
- free_saved (dtp);
-
- switch (nl->type)
- {
- case BT_INTEGER:
- read_integer (dtp, len);
- break;
-
- case BT_LOGICAL:
- read_logical (dtp, len);
- break;
-
- case BT_CHARACTER:
- read_character (dtp, len);
- break;
-
- case BT_REAL:
- /* Need to copy data back from the real location to the temp in order
- to handle nml reads into arrays. */
- read_real (dtp, pdata, len);
- memcpy (dtp->u.p.value, pdata, dlen);
- break;
-
- case BT_COMPLEX:
- /* Same as for REAL, copy back to temp. */
- read_complex (dtp, pdata, len, dlen);
- memcpy (dtp->u.p.value, pdata, dlen);
- break;
-
- case BT_DERIVED:
- obj_name_len = strlen (nl->var_name) + 1;
- obj_name = xmalloc (obj_name_len+1);
- memcpy (obj_name, nl->var_name, obj_name_len-1);
- memcpy (obj_name + obj_name_len - 1, "%", 2);
-
- /* If reading a derived type, disable the expanded read warning
- since a single object can have multiple reads. */
- dtp->u.p.expanded_read = 0;
-
- /* Now loop over the components. */
-
- for (cmp = nl->next;
- cmp &&
- !strncmp (cmp->var_name, obj_name, obj_name_len);
- cmp = cmp->next)
- {
- /* Jump over nested derived type by testing if the potential
- component name contains '%'. */
- if (strchr (cmp->var_name + obj_name_len, '%'))
- continue;
-
- if (nml_read_obj (dtp, cmp, (index_type)(pdata - nl->mem_pos),
- pprev_nl, nml_err_msg, nml_err_msg_size,
- clow, chigh) == FAILURE)
- {
- free (obj_name);
- return FAILURE;
- }
-
- if (dtp->u.p.input_complete)
- {
- free (obj_name);
- return SUCCESS;
- }
- }
-
- free (obj_name);
- goto incr_idx;
-
- default:
- snprintf (nml_err_msg, nml_err_msg_size,
- "Bad type for namelist object %s", nl->var_name);
- internal_error (&dtp->common, nml_err_msg);
- goto nml_err_ret;
- }
- }
-
- /* The standard permits array data to stop short of the number of
- elements specified in the loop specification. In this case, we
- should be here with dtp->u.p.nml_read_error != 0. Control returns to
- nml_get_obj_data and an attempt is made to read object name. */
-
- *pprev_nl = nl;
- if (dtp->u.p.nml_read_error)
- {
- dtp->u.p.expanded_read = 0;
- return SUCCESS;
- }
-
- if (dtp->u.p.saved_type == BT_UNKNOWN)
- {
- dtp->u.p.expanded_read = 0;
- goto incr_idx;
- }
-
- switch (dtp->u.p.saved_type)
- {
-
- case BT_COMPLEX:
- case BT_REAL:
- case BT_INTEGER:
- case BT_LOGICAL:
- memcpy (pdata, dtp->u.p.value, dlen);
- break;
-
- case BT_CHARACTER:
- if (dlen < dtp->u.p.saved_used)
- {
- if (compile_options.bounds_check)
- {
- snprintf (nml_err_msg, nml_err_msg_size,
- "Namelist object '%s' truncated on read.",
- nl->var_name);
- generate_warning (&dtp->common, nml_err_msg);
- }
- m = dlen;
- }
- else
- m = dtp->u.p.saved_used;
- pdata = (void*)( pdata + clow - 1 );
- memcpy (pdata, dtp->u.p.saved_string, m);
- if (m < dlen)
- memset ((void*)( pdata + m ), ' ', dlen - m);
- break;
-
- default:
- break;
- }
-
- /* Warn if a non-standard expanded read occurs. A single read of a
- single object is acceptable. If a second read occurs, issue a warning
- and set the flag to zero to prevent further warnings. */
- if (dtp->u.p.expanded_read == 2)
- {
- notify_std (&dtp->common, GFC_STD_GNU, "Non-standard expanded namelist read.");
- dtp->u.p.expanded_read = 0;
- }
-
- /* If the expanded read warning flag is set, increment it,
- indicating that a single read has occurred. */
- if (dtp->u.p.expanded_read >= 1)
- dtp->u.p.expanded_read++;
-
- /* Break out of loop if scalar. */
- if (!nl->var_rank)
- break;
-
- /* Now increment the index vector. */
-
-incr_idx:
-
- nml_carry = 1;
- for (dim = 0; dim < nl->var_rank; dim++)
- {
- nl->ls[dim].idx += nml_carry * nl->ls[dim].step;
- nml_carry = 0;
- if (((nl->ls[dim].step > 0) && (nl->ls[dim].idx > nl->ls[dim].end))
- ||
- ((nl->ls[dim].step < 0) && (nl->ls[dim].idx < nl->ls[dim].end)))
- {
- nl->ls[dim].idx = nl->ls[dim].start;
- nml_carry = 1;
- }
- }
- } while (!nml_carry);
-
- if (dtp->u.p.repeat_count > 1)
- {
- snprintf (nml_err_msg, nml_err_msg_size,
- "Repeat count too large for namelist object %s", nl->var_name);
- goto nml_err_ret;
- }
- return SUCCESS;
-
-nml_err_ret:
-
- return FAILURE;
-}
-
-/* Parses the object name, including array and substring qualifiers. It
- iterates over derived type components, touching those components and
- setting their loop specifications, if there is a qualifier. If the
- object is itself a derived type, its components and subcomponents are
- touched. nml_read_obj is called at the end and this reads the data in
- the manner specified by the object name. */
-
-static try
-nml_get_obj_data (st_parameter_dt *dtp, namelist_info **pprev_nl,
- char *nml_err_msg, size_t nml_err_msg_size)
-{
- int c;
- namelist_info * nl;
- namelist_info * first_nl = NULL;
- namelist_info * root_nl = NULL;
- int dim, parsed_rank;
- int component_flag, qualifier_flag;
- index_type clow, chigh;
- int non_zero_rank_count;
-
- /* Look for end of input or object name. If '?' or '=?' are encountered
- in stdin, print the node names or the namelist to stdout. */
-
- eat_separator (dtp);
- if (dtp->u.p.input_complete)
- return SUCCESS;
-
- if (dtp->u.p.at_eol)
- finish_separator (dtp);
- if (dtp->u.p.input_complete)
- return SUCCESS;
-
- if ((c = next_char (dtp)) == EOF)
- goto nml_err_ret;
- switch (c)
- {
- case '=':
- if ((c = next_char (dtp)) == EOF)
- goto nml_err_ret;
- if (c != '?')
- {
- snprintf (nml_err_msg, nml_err_msg_size,
- "namelist read: misplaced = sign");
- goto nml_err_ret;
- }
- nml_query (dtp, '=');
- return SUCCESS;
-
- case '?':
- nml_query (dtp, '?');
- return SUCCESS;
-
- case '$':
- case '&':
- nml_match_name (dtp, "end", 3);
- if (dtp->u.p.nml_read_error)
- {
- snprintf (nml_err_msg, nml_err_msg_size,
- "namelist not terminated with / or &end");
- goto nml_err_ret;
- }
- case '/':
- dtp->u.p.input_complete = 1;
- return SUCCESS;
-
- default :
- break;
- }
-
- /* Untouch all nodes of the namelist and reset the flags that are set for
- derived type components. */
-
- nml_untouch_nodes (dtp);
- component_flag = 0;
- qualifier_flag = 0;
- non_zero_rank_count = 0;
-
- /* Get the object name - should '!' and '\n' be permitted separators? */
-
-get_name:
-
- free_saved (dtp);
-
- do
- {
- if (!is_separator (c))
- push_char (dtp, tolower(c));
- if ((c = next_char (dtp)) == EOF)
- goto nml_err_ret;
- }
- while (!( c=='=' || c==' ' || c=='\t' || c =='(' || c =='%' ));
-
- unget_char (dtp, c);
-
- /* Check that the name is in the namelist and get pointer to object.
- Three error conditions exist: (i) An attempt is being made to
- identify a non-existent object, following a failed data read or
- (ii) The object name does not exist or (iii) Too many data items
- are present for an object. (iii) gives the same error message
- as (i) */
-
- push_char (dtp, '\0');
-
- if (component_flag)
- {
- size_t var_len = strlen (root_nl->var_name);
- size_t saved_len
- = dtp->u.p.saved_string ? strlen (dtp->u.p.saved_string) : 0;
- char ext_name[var_len + saved_len + 1];
-
- memcpy (ext_name, root_nl->var_name, var_len);
- if (dtp->u.p.saved_string)
- memcpy (ext_name + var_len, dtp->u.p.saved_string, saved_len);
- ext_name[var_len + saved_len] = '\0';
- nl = find_nml_node (dtp, ext_name);
- }
- else
- nl = find_nml_node (dtp, dtp->u.p.saved_string);
-
- if (nl == NULL)
- {
- if (dtp->u.p.nml_read_error && *pprev_nl)
- snprintf (nml_err_msg, nml_err_msg_size,
- "Bad data for namelist object %s", (*pprev_nl)->var_name);
-
- else
- snprintf (nml_err_msg, nml_err_msg_size,
- "Cannot match namelist object name %s",
- dtp->u.p.saved_string);
-
- goto nml_err_ret;
- }
-
- /* Get the length, data length, base pointer and rank of the variable.
- Set the default loop specification first. */
-
- for (dim=0; dim < nl->var_rank; dim++)
- {
- nl->ls[dim].step = 1;
- nl->ls[dim].end = GFC_DESCRIPTOR_UBOUND(nl,dim);
- nl->ls[dim].start = GFC_DESCRIPTOR_LBOUND(nl,dim);
- nl->ls[dim].idx = nl->ls[dim].start;
- }
-
-/* Check to see if there is a qualifier: if so, parse it.*/
-
- if (c == '(' && nl->var_rank)
- {
- parsed_rank = 0;
- if (nml_parse_qualifier (dtp, nl->dim, nl->ls, nl->var_rank,
- nl->type, nml_err_msg, nml_err_msg_size,
- &parsed_rank) == FAILURE)
- {
- char *nml_err_msg_end = strchr (nml_err_msg, '\0');
- snprintf (nml_err_msg_end,
- nml_err_msg_size - (nml_err_msg_end - nml_err_msg),
- " for namelist variable %s", nl->var_name);
- goto nml_err_ret;
- }
- if (parsed_rank > 0)
- non_zero_rank_count++;
-
- qualifier_flag = 1;
-
- if ((c = next_char (dtp)) == EOF)
- goto nml_err_ret;
- unget_char (dtp, c);
- }
- else if (nl->var_rank > 0)
- non_zero_rank_count++;
-
- /* Now parse a derived type component. The root namelist_info address
- is backed up, as is the previous component level. The component flag
- is set and the iteration is made by jumping back to get_name. */
-
- if (c == '%')
- {
- if (nl->type != BT_DERIVED)
- {
- snprintf (nml_err_msg, nml_err_msg_size,
- "Attempt to get derived component for %s", nl->var_name);
- goto nml_err_ret;
- }
-
- /* Don't move first_nl further in the list if a qualifier was found. */
- if ((*pprev_nl == NULL && !qualifier_flag) || !component_flag)
- first_nl = nl;
-
- root_nl = nl;
-
- component_flag = 1;
- if ((c = next_char (dtp)) == EOF)
- goto nml_err_ret;
- goto get_name;
- }
-
- /* Parse a character qualifier, if present. chigh = 0 is a default
- that signals that the string length = string_length. */
-
- clow = 1;
- chigh = 0;
-
- if (c == '(' && nl->type == BT_CHARACTER)
- {
- descriptor_dimension chd[1] = { {1, clow, nl->string_length} };
- array_loop_spec ind[1] = { {1, clow, nl->string_length, 1} };
-
- if (nml_parse_qualifier (dtp, chd, ind, -1, nl->type,
- nml_err_msg, nml_err_msg_size, &parsed_rank)
- == FAILURE)
- {
- char *nml_err_msg_end = strchr (nml_err_msg, '\0');
- snprintf (nml_err_msg_end,
- nml_err_msg_size - (nml_err_msg_end - nml_err_msg),
- " for namelist variable %s", nl->var_name);
- goto nml_err_ret;
- }
-
- clow = ind[0].start;
- chigh = ind[0].end;
-
- if (ind[0].step != 1)
- {
- snprintf (nml_err_msg, nml_err_msg_size,
- "Step not allowed in substring qualifier"
- " for namelist object %s", nl->var_name);
- goto nml_err_ret;
- }
-
- if ((c = next_char (dtp)) == EOF)
- goto nml_err_ret;
- unget_char (dtp, c);
- }
-
- /* Make sure no extraneous qualifiers are there. */
-
- if (c == '(')
- {
- snprintf (nml_err_msg, nml_err_msg_size,
- "Qualifier for a scalar or non-character namelist object %s",
- nl->var_name);
- goto nml_err_ret;
- }
-
- /* Make sure there is no more than one non-zero rank object. */
- if (non_zero_rank_count > 1)
- {
- snprintf (nml_err_msg, nml_err_msg_size,
- "Multiple sub-objects with non-zero rank in namelist object %s",
- nl->var_name);
- non_zero_rank_count = 0;
- goto nml_err_ret;
- }
-
-/* According to the standard, an equal sign MUST follow an object name. The
- following is possibly lax - it allows comments, blank lines and so on to
- intervene. eat_spaces (dtp); c = next_char (dtp); would be compliant*/
-
- free_saved (dtp);
-
- eat_separator (dtp);
- if (dtp->u.p.input_complete)
- return SUCCESS;
-
- if (dtp->u.p.at_eol)
- finish_separator (dtp);
- if (dtp->u.p.input_complete)
- return SUCCESS;
-
- if ((c = next_char (dtp)) == EOF)
- goto nml_err_ret;
-
- if (c != '=')
- {
- snprintf (nml_err_msg, nml_err_msg_size,
- "Equal sign must follow namelist object name %s",
- nl->var_name);
- goto nml_err_ret;
- }
- /* If a derived type, touch its components and restore the root
- namelist_info if we have parsed a qualified derived type
- component. */
-
- if (nl->type == BT_DERIVED)
- nml_touch_nodes (nl);
-
- if (first_nl)
- {
- if (first_nl->var_rank == 0)
- {
- if (component_flag && qualifier_flag)
- nl = first_nl;
- }
- else
- nl = first_nl;
- }
-
- if (nml_read_obj (dtp, nl, 0, pprev_nl, nml_err_msg, nml_err_msg_size,
- clow, chigh) == FAILURE)
- goto nml_err_ret;
-
- return SUCCESS;
-
-nml_err_ret:
-
- /* The EOF error message is issued by hit_eof. Return true so that the
- caller does not use nml_err_msg and nml_err_msg_size to generate
- an unrelated error message. */
- if (c == EOF)
- {
- dtp->u.p.input_complete = 1;
- unget_char (dtp, c);
- hit_eof (dtp);
- return SUCCESS;
- }
-
- return FAILURE;
-}
-
-/* Entry point for namelist input. Goes through input until namelist name
- is matched. Then cycles through nml_get_obj_data until the input is
- completed or there is an error. */
-
-void
-namelist_read (st_parameter_dt *dtp)
-{
- int c;
- char nml_err_msg[200];
-
- /* Initialize the error string buffer just in case we get an unexpected fail
- somewhere and end up at nml_err_ret. */
- strcpy (nml_err_msg, "Internal namelist read error");
-
- /* Pointer to the previously read object, in case attempt is made to read
- new object name. Should this fail, error message can give previous
- name. */
- namelist_info *prev_nl = NULL;
-
- dtp->u.p.namelist_mode = 1;
- dtp->u.p.input_complete = 0;
- dtp->u.p.expanded_read = 0;
-
- /* Look for &namelist_name . Skip all characters, testing for $nmlname.
- Exit on success or EOF. If '?' or '=?' encountered in stdin, print
- node names or namelist on stdout. */
-
-find_nml_name:
- c = next_char (dtp);
- switch (c)
- {
- case '$':
- case '&':
- break;
-
- case '!':
- eat_line (dtp);
- goto find_nml_name;
-
- case '=':
- c = next_char (dtp);
- if (c == '?')
- nml_query (dtp, '=');
- else
- unget_char (dtp, c);
- goto find_nml_name;
-
- case '?':
- nml_query (dtp, '?');
- goto find_nml_name;
-
- case EOF:
- return;
-
- default:
- goto find_nml_name;
- }
-
- /* Match the name of the namelist. */
-
- nml_match_name (dtp, dtp->namelist_name, dtp->namelist_name_len);
-
- if (dtp->u.p.nml_read_error)
- goto find_nml_name;
-
- /* A trailing space is required, we give a little latitude here, 10.9.1. */
- c = next_char (dtp);
- if (!is_separator(c) && c != '!')
- {
- unget_char (dtp, c);
- goto find_nml_name;
- }
-
- unget_char (dtp, c);
- eat_separator (dtp);
-
- /* Ready to read namelist objects. If there is an error in input
- from stdin, output the error message and continue. */
-
- while (!dtp->u.p.input_complete)
- {
- if (nml_get_obj_data (dtp, &prev_nl, nml_err_msg, sizeof nml_err_msg)
- == FAILURE)
- {
- if (dtp->u.p.current_unit->unit_number != options.stdin_unit)
- goto nml_err_ret;
- generate_error (&dtp->common, LIBERROR_READ_VALUE, nml_err_msg);
- }
-
- /* Reset the previous namelist pointer if we know we are not going
- to be doing multiple reads within a single namelist object. */
- if (prev_nl && prev_nl->var_rank == 0)
- prev_nl = NULL;
- }
-
- free_saved (dtp);
- free_line (dtp);
- return;
-
-
-nml_err_ret:
-
- /* All namelist error calls return from here */
- free_saved (dtp);
- free_line (dtp);
- generate_error (&dtp->common, LIBERROR_READ_VALUE, nml_err_msg);
- return;
-}
diff --git a/gcc-4.8.1/libgfortran/io/lock.c b/gcc-4.8.1/libgfortran/io/lock.c
deleted file mode 100644
index dbb61a7dc..000000000
--- a/gcc-4.8.1/libgfortran/io/lock.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Thread/recursion locking
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Paul Brook <paul@nowt.org> and Andy Vaught
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public
-License as published by the Free Software Foundation; either
-version 3 of the License, or (at your option) any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "io.h"
-#include <string.h>
-#include <stdlib.h>
-
-/* library_start()-- Called with a library call is entered. */
-
-void
-library_start (st_parameter_common *cmp)
-{
- if ((cmp->flags & IOPARM_LIBRETURN_ERROR) != 0)
- return;
-
- cmp->flags &= ~IOPARM_LIBRETURN_MASK;
-}
-
-
-void
-free_ionml (st_parameter_dt *dtp)
-{
- namelist_info * t1, *t2;
-
- /* Delete the namelist, if it exists. */
-
- if (dtp->u.p.ionml != NULL)
- {
- t1 = dtp->u.p.ionml;
- while (t1 != NULL)
- {
- t2 = t1;
- t1 = t1->next;
- free (t2->var_name);
- if (t2->var_rank)
- {
- free (t2->dim);
- free (t2->ls);
- }
- free (t2);
- }
- }
- dtp->u.p.ionml = NULL;
-}
diff --git a/gcc-4.8.1/libgfortran/io/open.c b/gcc-4.8.1/libgfortran/io/open.c
deleted file mode 100644
index d9cfde853..000000000
--- a/gcc-4.8.1/libgfortran/io/open.c
+++ /dev/null
@@ -1,868 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "io.h"
-#include "fbuf.h"
-#include "unix.h"
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-
-static const st_option access_opt[] = {
- {"sequential", ACCESS_SEQUENTIAL},
- {"direct", ACCESS_DIRECT},
- {"append", ACCESS_APPEND},
- {"stream", ACCESS_STREAM},
- {NULL, 0}
-};
-
-static const st_option action_opt[] =
-{
- { "read", ACTION_READ},
- { "write", ACTION_WRITE},
- { "readwrite", ACTION_READWRITE},
- { NULL, 0}
-};
-
-static const st_option blank_opt[] =
-{
- { "null", BLANK_NULL},
- { "zero", BLANK_ZERO},
- { NULL, 0}
-};
-
-static const st_option delim_opt[] =
-{
- { "none", DELIM_NONE},
- { "apostrophe", DELIM_APOSTROPHE},
- { "quote", DELIM_QUOTE},
- { NULL, 0}
-};
-
-static const st_option form_opt[] =
-{
- { "formatted", FORM_FORMATTED},
- { "unformatted", FORM_UNFORMATTED},
- { NULL, 0}
-};
-
-static const st_option position_opt[] =
-{
- { "asis", POSITION_ASIS},
- { "rewind", POSITION_REWIND},
- { "append", POSITION_APPEND},
- { NULL, 0}
-};
-
-static const st_option status_opt[] =
-{
- { "unknown", STATUS_UNKNOWN},
- { "old", STATUS_OLD},
- { "new", STATUS_NEW},
- { "replace", STATUS_REPLACE},
- { "scratch", STATUS_SCRATCH},
- { NULL, 0}
-};
-
-static const st_option pad_opt[] =
-{
- { "yes", PAD_YES},
- { "no", PAD_NO},
- { NULL, 0}
-};
-
-static const st_option decimal_opt[] =
-{
- { "point", DECIMAL_POINT},
- { "comma", DECIMAL_COMMA},
- { NULL, 0}
-};
-
-static const st_option encoding_opt[] =
-{
- { "utf-8", ENCODING_UTF8},
- { "default", ENCODING_DEFAULT},
- { NULL, 0}
-};
-
-static const st_option round_opt[] =
-{
- { "up", ROUND_UP},
- { "down", ROUND_DOWN},
- { "zero", ROUND_ZERO},
- { "nearest", ROUND_NEAREST},
- { "compatible", ROUND_COMPATIBLE},
- { "processor_defined", ROUND_PROCDEFINED},
- { NULL, 0}
-};
-
-static const st_option sign_opt[] =
-{
- { "plus", SIGN_PLUS},
- { "suppress", SIGN_SUPPRESS},
- { "processor_defined", SIGN_PROCDEFINED},
- { NULL, 0}
-};
-
-static const st_option convert_opt[] =
-{
- { "native", GFC_CONVERT_NATIVE},
- { "swap", GFC_CONVERT_SWAP},
- { "big_endian", GFC_CONVERT_BIG},
- { "little_endian", GFC_CONVERT_LITTLE},
- { NULL, 0}
-};
-
-static const st_option async_opt[] =
-{
- { "yes", ASYNC_YES},
- { "no", ASYNC_NO},
- { NULL, 0}
-};
-
-/* Given a unit, test to see if the file is positioned at the terminal
- point, and if so, change state from NO_ENDFILE flag to AT_ENDFILE.
- This prevents us from changing the state from AFTER_ENDFILE to
- AT_ENDFILE. */
-
-static void
-test_endfile (gfc_unit * u)
-{
- if (u->endfile == NO_ENDFILE)
- {
- gfc_offset sz = ssize (u->s);
- if (sz == 0 || sz == stell (u->s))
- u->endfile = AT_ENDFILE;
- }
-}
-
-
-/* Change the modes of a file, those that are allowed * to be
- changed. */
-
-static void
-edit_modes (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
-{
- /* Complain about attempts to change the unchangeable. */
-
- if (flags->status != STATUS_UNSPECIFIED && flags->status != STATUS_OLD &&
- u->flags.status != flags->status)
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "Cannot change STATUS parameter in OPEN statement");
-
- if (flags->access != ACCESS_UNSPECIFIED && u->flags.access != flags->access)
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "Cannot change ACCESS parameter in OPEN statement");
-
- if (flags->form != FORM_UNSPECIFIED && u->flags.form != flags->form)
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "Cannot change FORM parameter in OPEN statement");
-
- if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN)
- && opp->recl_in != u->recl)
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "Cannot change RECL parameter in OPEN statement");
-
- if (flags->action != ACTION_UNSPECIFIED && u->flags.action != flags->action)
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "Cannot change ACTION parameter in OPEN statement");
-
- /* Status must be OLD if present. */
-
- if (flags->status != STATUS_UNSPECIFIED && flags->status != STATUS_OLD &&
- flags->status != STATUS_UNKNOWN)
- {
- if (flags->status == STATUS_SCRATCH)
- notify_std (&opp->common, GFC_STD_GNU,
- "OPEN statement must have a STATUS of OLD or UNKNOWN");
- else
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "OPEN statement must have a STATUS of OLD or UNKNOWN");
- }
-
- if (u->flags.form == FORM_UNFORMATTED)
- {
- if (flags->delim != DELIM_UNSPECIFIED)
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "DELIM parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
-
- if (flags->blank != BLANK_UNSPECIFIED)
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "BLANK parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
-
- if (flags->pad != PAD_UNSPECIFIED)
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "PAD parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
-
- if (flags->decimal != DECIMAL_UNSPECIFIED)
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "DECIMAL parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
-
- if (flags->encoding != ENCODING_UNSPECIFIED)
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "ENCODING parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
-
- if (flags->round != ROUND_UNSPECIFIED)
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "ROUND parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
-
- if (flags->sign != SIGN_UNSPECIFIED)
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "SIGN parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
- }
-
- if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
- {
- /* Change the changeable: */
- if (flags->blank != BLANK_UNSPECIFIED)
- u->flags.blank = flags->blank;
- if (flags->delim != DELIM_UNSPECIFIED)
- u->flags.delim = flags->delim;
- if (flags->pad != PAD_UNSPECIFIED)
- u->flags.pad = flags->pad;
- if (flags->decimal != DECIMAL_UNSPECIFIED)
- u->flags.decimal = flags->decimal;
- if (flags->encoding != ENCODING_UNSPECIFIED)
- u->flags.encoding = flags->encoding;
- if (flags->async != ASYNC_UNSPECIFIED)
- u->flags.async = flags->async;
- if (flags->round != ROUND_UNSPECIFIED)
- u->flags.round = flags->round;
- if (flags->sign != SIGN_UNSPECIFIED)
- u->flags.sign = flags->sign;
- }
-
- /* Reposition the file if necessary. */
-
- switch (flags->position)
- {
- case POSITION_UNSPECIFIED:
- case POSITION_ASIS:
- break;
-
- case POSITION_REWIND:
- if (sseek (u->s, 0, SEEK_SET) != 0)
- goto seek_error;
-
- u->current_record = 0;
- u->last_record = 0;
-
- test_endfile (u);
- break;
-
- case POSITION_APPEND:
- if (sseek (u->s, 0, SEEK_END) < 0)
- goto seek_error;
-
- if (flags->access != ACCESS_STREAM)
- u->current_record = 0;
-
- u->endfile = AT_ENDFILE; /* We are at the end. */
- break;
-
- seek_error:
- generate_error (&opp->common, LIBERROR_OS, NULL);
- break;
- }
-
- unlock_unit (u);
-}
-
-
-/* Open an unused unit. */
-
-gfc_unit *
-new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
-{
- gfc_unit *u2;
- stream *s;
- char tmpname[5 /* fort. */ + 10 /* digits of unit number */ + 1 /* 0 */];
-
- /* Change unspecifieds to defaults. Leave (flags->action ==
- ACTION_UNSPECIFIED) alone so open_external() can set it based on
- what type of open actually works. */
-
- if (flags->access == ACCESS_UNSPECIFIED)
- flags->access = ACCESS_SEQUENTIAL;
-
- if (flags->form == FORM_UNSPECIFIED)
- flags->form = (flags->access == ACCESS_SEQUENTIAL)
- ? FORM_FORMATTED : FORM_UNFORMATTED;
-
- if (flags->async == ASYNC_UNSPECIFIED)
- flags->async = ASYNC_NO;
-
- if (flags->status == STATUS_UNSPECIFIED)
- flags->status = STATUS_UNKNOWN;
-
- /* Checks. */
-
- if (flags->delim == DELIM_UNSPECIFIED)
- flags->delim = DELIM_NONE;
- else
- {
- if (flags->form == FORM_UNFORMATTED)
- {
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "DELIM parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
- goto fail;
- }
- }
-
- if (flags->blank == BLANK_UNSPECIFIED)
- flags->blank = BLANK_NULL;
- else
- {
- if (flags->form == FORM_UNFORMATTED)
- {
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "BLANK parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
- goto fail;
- }
- }
-
- if (flags->pad == PAD_UNSPECIFIED)
- flags->pad = PAD_YES;
- else
- {
- if (flags->form == FORM_UNFORMATTED)
- {
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "PAD parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
- goto fail;
- }
- }
-
- if (flags->decimal == DECIMAL_UNSPECIFIED)
- flags->decimal = DECIMAL_POINT;
- else
- {
- if (flags->form == FORM_UNFORMATTED)
- {
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "DECIMAL parameter conflicts with UNFORMATTED form "
- "in OPEN statement");
- goto fail;
- }
- }
-
- if (flags->encoding == ENCODING_UNSPECIFIED)
- flags->encoding = ENCODING_DEFAULT;
- else
- {
- if (flags->form == FORM_UNFORMATTED)
- {
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "ENCODING parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
- goto fail;
- }
- }
-
- /* NB: the value for ROUND when it's not specified by the user does not
- have to be PROCESSOR_DEFINED; the standard says that it is
- processor dependent, and requires that it is one of the
- possible value (see F2003, 9.4.5.13). */
- if (flags->round == ROUND_UNSPECIFIED)
- flags->round = ROUND_PROCDEFINED;
- else
- {
- if (flags->form == FORM_UNFORMATTED)
- {
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "ROUND parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
- goto fail;
- }
- }
-
- if (flags->sign == SIGN_UNSPECIFIED)
- flags->sign = SIGN_PROCDEFINED;
- else
- {
- if (flags->form == FORM_UNFORMATTED)
- {
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "SIGN parameter conflicts with UNFORMATTED form in "
- "OPEN statement");
- goto fail;
- }
- }
-
- if (flags->position != POSITION_ASIS && flags->access == ACCESS_DIRECT)
- {
- generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
- "ACCESS parameter conflicts with SEQUENTIAL access in "
- "OPEN statement");
- goto fail;
- }
- else
- if (flags->position == POSITION_UNSPECIFIED)
- flags->position = POSITION_ASIS;
-
- if (flags->access == ACCESS_DIRECT
- && (opp->common.flags & IOPARM_OPEN_HAS_RECL_IN) == 0)
- {
- generate_error (&opp->common, LIBERROR_MISSING_OPTION,
- "Missing RECL parameter in OPEN statement");
- goto fail;
- }
-
- if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN) && opp->recl_in <= 0)
- {
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "RECL parameter is non-positive in OPEN statement");
- goto fail;
- }
-
- switch (flags->status)
- {
- case STATUS_SCRATCH:
- if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) == 0)
- {
- opp->file = NULL;
- break;
- }
-
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "FILE parameter must not be present in OPEN statement");
- goto fail;
-
- case STATUS_OLD:
- case STATUS_NEW:
- case STATUS_REPLACE:
- case STATUS_UNKNOWN:
- if ((opp->common.flags & IOPARM_OPEN_HAS_FILE))
- break;
-
- opp->file = tmpname;
- opp->file_len = snprintf(opp->file, sizeof (tmpname), "fort.%d",
- (int) opp->common.unit);
- break;
-
- default:
- internal_error (&opp->common, "new_unit(): Bad status");
- }
-
- /* Make sure the file isn't already open someplace else.
- Do not error if opening file preconnected to stdin, stdout, stderr. */
-
- u2 = NULL;
- if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) != 0)
- u2 = find_file (opp->file, opp->file_len);
- if (u2 != NULL
- && (options.stdin_unit < 0 || u2->unit_number != options.stdin_unit)
- && (options.stdout_unit < 0 || u2->unit_number != options.stdout_unit)
- && (options.stderr_unit < 0 || u2->unit_number != options.stderr_unit))
- {
- unlock_unit (u2);
- generate_error (&opp->common, LIBERROR_ALREADY_OPEN, NULL);
- goto cleanup;
- }
-
- if (u2 != NULL)
- unlock_unit (u2);
-
- /* Open file. */
-
- s = open_external (opp, flags);
- if (s == NULL)
- {
- char *path, *msg;
- size_t msglen;
- path = (char *) gfc_alloca (opp->file_len + 1);
- msglen = opp->file_len + 51;
- msg = (char *) gfc_alloca (msglen);
- unpack_filename (path, opp->file, opp->file_len);
-
- switch (errno)
- {
- case ENOENT:
- snprintf (msg, msglen, "File '%s' does not exist", path);
- break;
-
- case EEXIST:
- snprintf (msg, msglen, "File '%s' already exists", path);
- break;
-
- case EACCES:
- snprintf (msg, msglen,
- "Permission denied trying to open file '%s'", path);
- break;
-
- case EISDIR:
- snprintf (msg, msglen, "'%s' is a directory", path);
- break;
-
- default:
- msg = NULL;
- }
-
- generate_error (&opp->common, LIBERROR_OS, msg);
- goto cleanup;
- }
-
- if (flags->status == STATUS_NEW || flags->status == STATUS_REPLACE)
- flags->status = STATUS_OLD;
-
- /* Create the unit structure. */
-
- u->file = xmalloc (opp->file_len);
- if (u->unit_number != opp->common.unit)
- internal_error (&opp->common, "Unit number changed");
- u->s = s;
- u->flags = *flags;
- u->read_bad = 0;
- u->endfile = NO_ENDFILE;
- u->last_record = 0;
- u->current_record = 0;
- u->mode = READING;
- u->maxrec = 0;
- u->bytes_left = 0;
- u->saved_pos = 0;
-
- if (flags->position == POSITION_APPEND)
- {
- if (sseek (u->s, 0, SEEK_END) < 0)
- generate_error (&opp->common, LIBERROR_OS, NULL);
- u->endfile = AT_ENDFILE;
- }
-
- /* Unspecified recl ends up with a processor dependent value. */
-
- if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
- {
- u->flags.has_recl = 1;
- u->recl = opp->recl_in;
- u->recl_subrecord = u->recl;
- u->bytes_left = u->recl;
- }
- else
- {
- u->flags.has_recl = 0;
- u->recl = max_offset;
- if (compile_options.max_subrecord_length)
- {
- u->recl_subrecord = compile_options.max_subrecord_length;
- }
- else
- {
- switch (compile_options.record_marker)
- {
- case 0:
- /* Fall through */
- case sizeof (GFC_INTEGER_4):
- u->recl_subrecord = GFC_MAX_SUBRECORD_LENGTH;
- break;
-
- case sizeof (GFC_INTEGER_8):
- u->recl_subrecord = max_offset - 16;
- break;
-
- default:
- runtime_error ("Illegal value for record marker");
- break;
- }
- }
- }
-
- /* If the file is direct access, calculate the maximum record number
- via a division now instead of letting the multiplication overflow
- later. */
-
- if (flags->access == ACCESS_DIRECT)
- u->maxrec = max_offset / u->recl;
-
- if (flags->access == ACCESS_STREAM)
- {
- u->maxrec = max_offset;
- u->recl = 1;
- u->bytes_left = 1;
- u->strm_pos = stell (u->s) + 1;
- }
-
- memmove (u->file, opp->file, opp->file_len);
- u->file_len = opp->file_len;
-
- /* Curiously, the standard requires that the
- position specifier be ignored for new files so a newly connected
- file starts out at the initial point. We still need to figure
- out if the file is at the end or not. */
-
- test_endfile (u);
-
- if (flags->status == STATUS_SCRATCH && opp->file != NULL)
- free (opp->file);
-
- if (flags->form == FORM_FORMATTED)
- {
- if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
- fbuf_init (u, u->recl);
- else
- fbuf_init (u, 0);
- }
- else
- u->fbuf = NULL;
-
-
-
- return u;
-
- cleanup:
-
- /* Free memory associated with a temporary filename. */
-
- if (flags->status == STATUS_SCRATCH && opp->file != NULL)
- free (opp->file);
-
- fail:
-
- close_unit (u);
- return NULL;
-}
-
-
-/* Open a unit which is already open. This involves changing the
- modes or closing what is there now and opening the new file. */
-
-static void
-already_open (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
-{
- if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) == 0)
- {
- edit_modes (opp, u, flags);
- return;
- }
-
- /* If the file is connected to something else, close it and open a
- new unit. */
-
- if (!compare_file_filename (u, opp->file, opp->file_len))
- {
-#if !HAVE_UNLINK_OPEN_FILE
- char *path = NULL;
- if (u->file && u->flags.status == STATUS_SCRATCH)
- {
- path = (char *) gfc_alloca (u->file_len + 1);
- unpack_filename (path, u->file, u->file_len);
- }
-#endif
-
- if (sclose (u->s) == -1)
- {
- unlock_unit (u);
- generate_error (&opp->common, LIBERROR_OS,
- "Error closing file in OPEN statement");
- return;
- }
-
- u->s = NULL;
- free (u->file);
- u->file = NULL;
- u->file_len = 0;
-
-#if !HAVE_UNLINK_OPEN_FILE
- if (path != NULL)
- unlink (path);
-#endif
-
- u = new_unit (opp, u, flags);
- if (u != NULL)
- unlock_unit (u);
- return;
- }
-
- edit_modes (opp, u, flags);
-}
-
-
-/* Open file. */
-
-extern void st_open (st_parameter_open *opp);
-export_proto(st_open);
-
-void
-st_open (st_parameter_open *opp)
-{
- unit_flags flags;
- gfc_unit *u = NULL;
- GFC_INTEGER_4 cf = opp->common.flags;
- unit_convert conv;
-
- library_start (&opp->common);
-
- /* Decode options. */
-
- flags.access = !(cf & IOPARM_OPEN_HAS_ACCESS) ? ACCESS_UNSPECIFIED :
- find_option (&opp->common, opp->access, opp->access_len,
- access_opt, "Bad ACCESS parameter in OPEN statement");
-
- flags.action = !(cf & IOPARM_OPEN_HAS_ACTION) ? ACTION_UNSPECIFIED :
- find_option (&opp->common, opp->action, opp->action_len,
- action_opt, "Bad ACTION parameter in OPEN statement");
-
- flags.blank = !(cf & IOPARM_OPEN_HAS_BLANK) ? BLANK_UNSPECIFIED :
- find_option (&opp->common, opp->blank, opp->blank_len,
- blank_opt, "Bad BLANK parameter in OPEN statement");
-
- flags.delim = !(cf & IOPARM_OPEN_HAS_DELIM) ? DELIM_UNSPECIFIED :
- find_option (&opp->common, opp->delim, opp->delim_len,
- delim_opt, "Bad DELIM parameter in OPEN statement");
-
- flags.pad = !(cf & IOPARM_OPEN_HAS_PAD) ? PAD_UNSPECIFIED :
- find_option (&opp->common, opp->pad, opp->pad_len,
- pad_opt, "Bad PAD parameter in OPEN statement");
-
- flags.decimal = !(cf & IOPARM_OPEN_HAS_DECIMAL) ? DECIMAL_UNSPECIFIED :
- find_option (&opp->common, opp->decimal, opp->decimal_len,
- decimal_opt, "Bad DECIMAL parameter in OPEN statement");
-
- flags.encoding = !(cf & IOPARM_OPEN_HAS_ENCODING) ? ENCODING_UNSPECIFIED :
- find_option (&opp->common, opp->encoding, opp->encoding_len,
- encoding_opt, "Bad ENCODING parameter in OPEN statement");
-
- flags.async = !(cf & IOPARM_OPEN_HAS_ASYNCHRONOUS) ? ASYNC_UNSPECIFIED :
- find_option (&opp->common, opp->asynchronous, opp->asynchronous_len,
- async_opt, "Bad ASYNCHRONOUS parameter in OPEN statement");
-
- flags.round = !(cf & IOPARM_OPEN_HAS_ROUND) ? ROUND_UNSPECIFIED :
- find_option (&opp->common, opp->round, opp->round_len,
- round_opt, "Bad ROUND parameter in OPEN statement");
-
- flags.sign = !(cf & IOPARM_OPEN_HAS_SIGN) ? SIGN_UNSPECIFIED :
- find_option (&opp->common, opp->sign, opp->sign_len,
- sign_opt, "Bad SIGN parameter in OPEN statement");
-
- flags.form = !(cf & IOPARM_OPEN_HAS_FORM) ? FORM_UNSPECIFIED :
- find_option (&opp->common, opp->form, opp->form_len,
- form_opt, "Bad FORM parameter in OPEN statement");
-
- flags.position = !(cf & IOPARM_OPEN_HAS_POSITION) ? POSITION_UNSPECIFIED :
- find_option (&opp->common, opp->position, opp->position_len,
- position_opt, "Bad POSITION parameter in OPEN statement");
-
- flags.status = !(cf & IOPARM_OPEN_HAS_STATUS) ? STATUS_UNSPECIFIED :
- find_option (&opp->common, opp->status, opp->status_len,
- status_opt, "Bad STATUS parameter in OPEN statement");
-
- /* First, we check wether the convert flag has been set via environment
- variable. This overrides the convert tag in the open statement. */
-
- conv = get_unformatted_convert (opp->common.unit);
-
- if (conv == GFC_CONVERT_NONE)
- {
- /* Nothing has been set by environment variable, check the convert tag. */
- if (cf & IOPARM_OPEN_HAS_CONVERT)
- conv = find_option (&opp->common, opp->convert, opp->convert_len,
- convert_opt,
- "Bad CONVERT parameter in OPEN statement");
- else
- conv = compile_options.convert;
- }
-
- /* We use big_endian, which is 0 on little-endian machines
- and 1 on big-endian machines. */
- switch (conv)
- {
- case GFC_CONVERT_NATIVE:
- case GFC_CONVERT_SWAP:
- break;
-
- case GFC_CONVERT_BIG:
- conv = big_endian ? GFC_CONVERT_NATIVE : GFC_CONVERT_SWAP;
- break;
-
- case GFC_CONVERT_LITTLE:
- conv = big_endian ? GFC_CONVERT_SWAP : GFC_CONVERT_NATIVE;
- break;
-
- default:
- internal_error (&opp->common, "Illegal value for CONVERT");
- break;
- }
-
- flags.convert = conv;
-
- if (!(opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT) && opp->common.unit < 0)
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "Bad unit number in OPEN statement");
-
- if (flags.position != POSITION_UNSPECIFIED
- && flags.access == ACCESS_DIRECT)
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "Cannot use POSITION with direct access files");
-
- if (flags.access == ACCESS_APPEND)
- {
- if (flags.position != POSITION_UNSPECIFIED
- && flags.position != POSITION_APPEND)
- generate_error (&opp->common, LIBERROR_BAD_OPTION,
- "Conflicting ACCESS and POSITION flags in"
- " OPEN statement");
-
- notify_std (&opp->common, GFC_STD_GNU,
- "Extension: APPEND as a value for ACCESS in OPEN statement");
- flags.access = ACCESS_SEQUENTIAL;
- flags.position = POSITION_APPEND;
- }
-
- if (flags.position == POSITION_UNSPECIFIED)
- flags.position = POSITION_ASIS;
-
- if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
- {
- if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT))
- opp->common.unit = get_unique_unit_number(opp);
-
- u = find_or_create_unit (opp->common.unit);
- if (u->s == NULL)
- {
- u = new_unit (opp, u, &flags);
- if (u != NULL)
- unlock_unit (u);
- }
- else
- already_open (opp, u, &flags);
- }
-
- if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT)
- && (opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
- *opp->newunit = opp->common.unit;
-
- library_end ();
-}
diff --git a/gcc-4.8.1/libgfortran/io/read.c b/gcc-4.8.1/libgfortran/io/read.c
deleted file mode 100644
index 2da1048f8..000000000
--- a/gcc-4.8.1/libgfortran/io/read.c
+++ /dev/null
@@ -1,1248 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "io.h"
-#include "fbuf.h"
-#include "format.h"
-#include "unix.h"
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <assert.h>
-
-typedef unsigned char uchar;
-
-/* read.c -- Deal with formatted reads */
-
-
-/* set_integer()-- All of the integer assignments come here to
- actually place the value into memory. */
-
-void
-set_integer (void *dest, GFC_INTEGER_LARGEST value, int length)
-{
- switch (length)
- {
-#ifdef HAVE_GFC_INTEGER_16
-/* length=10 comes about for kind=10 real/complex BOZ, cf. PR41711. */
- case 10:
- case 16:
- {
- GFC_INTEGER_16 tmp = value;
- memcpy (dest, (void *) &tmp, length);
- }
- break;
-#endif
- case 8:
- {
- GFC_INTEGER_8 tmp = value;
- memcpy (dest, (void *) &tmp, length);
- }
- break;
- case 4:
- {
- GFC_INTEGER_4 tmp = value;
- memcpy (dest, (void *) &tmp, length);
- }
- break;
- case 2:
- {
- GFC_INTEGER_2 tmp = value;
- memcpy (dest, (void *) &tmp, length);
- }
- break;
- case 1:
- {
- GFC_INTEGER_1 tmp = value;
- memcpy (dest, (void *) &tmp, length);
- }
- break;
- default:
- internal_error (NULL, "Bad integer kind");
- }
-}
-
-
-/* Max signed value of size give by length argument. */
-
-GFC_UINTEGER_LARGEST
-si_max (int length)
-{
- GFC_UINTEGER_LARGEST value;
-
- switch (length)
- {
-#if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
- case 16:
- case 10:
- value = 1;
- for (int n = 1; n < 4 * length; n++)
- value = (value << 2) + 3;
- return value;
-#endif
- case 8:
- return GFC_INTEGER_8_HUGE;
- case 4:
- return GFC_INTEGER_4_HUGE;
- case 2:
- return GFC_INTEGER_2_HUGE;
- case 1:
- return GFC_INTEGER_1_HUGE;
- default:
- internal_error (NULL, "Bad integer kind");
- }
-}
-
-
-/* convert_real()-- Convert a character representation of a floating
- point number to the machine number. Returns nonzero if there is an
- invalid input. Note: many architectures (e.g. IA-64, HP-PA)
- require that the storage pointed to by the dest argument is
- properly aligned for the type in question. */
-
-int
-convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
-{
- char *endptr = NULL;
-
- switch (length)
- {
- case 4:
- *((GFC_REAL_4*) dest) =
-#if defined(HAVE_STRTOF)
- gfc_strtof (buffer, &endptr);
-#else
- (GFC_REAL_4) gfc_strtod (buffer, &endptr);
-#endif
- break;
-
- case 8:
- *((GFC_REAL_8*) dest) = gfc_strtod (buffer, &endptr);
- break;
-
-#if defined(HAVE_GFC_REAL_10) && defined (HAVE_STRTOLD)
- case 10:
- *((GFC_REAL_10*) dest) = gfc_strtold (buffer, &endptr);
- break;
-#endif
-
-#if defined(HAVE_GFC_REAL_16)
-# if defined(GFC_REAL_16_IS_FLOAT128)
- case 16:
- *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, &endptr);
- break;
-# elif defined(HAVE_STRTOLD)
- case 16:
- *((GFC_REAL_16*) dest) = gfc_strtold (buffer, &endptr);
- break;
-# endif
-#endif
-
- default:
- internal_error (&dtp->common, "Unsupported real kind during IO");
- }
-
- if (buffer == endptr)
- {
- generate_error (&dtp->common, LIBERROR_READ_VALUE,
- "Error during floating point read");
- next_record (dtp, 1);
- return 1;
- }
-
- return 0;
-}
-
-/* convert_infnan()-- Convert character INF/NAN representation to the
- machine number. Note: many architectures (e.g. IA-64, HP-PA) require
- that the storage pointed to by the dest argument is properly aligned
- for the type in question. */
-
-int
-convert_infnan (st_parameter_dt *dtp, void *dest, const char *buffer,
- int length)
-{
- const char *s = buffer;
- int is_inf, plus = 1;
-
- if (*s == '+')
- s++;
- else if (*s == '-')
- {
- s++;
- plus = 0;
- }
-
- is_inf = *s == 'i';
-
- switch (length)
- {
- case 4:
- if (is_inf)
- *((GFC_REAL_4*) dest) = plus ? __builtin_inff () : -__builtin_inff ();
- else
- *((GFC_REAL_4*) dest) = plus ? __builtin_nanf ("") : -__builtin_nanf ("");
- break;
-
- case 8:
- if (is_inf)
- *((GFC_REAL_8*) dest) = plus ? __builtin_inf () : -__builtin_inf ();
- else
- *((GFC_REAL_8*) dest) = plus ? __builtin_nan ("") : -__builtin_nan ("");
- break;
-
-#if defined(HAVE_GFC_REAL_10)
- case 10:
- if (is_inf)
- *((GFC_REAL_10*) dest) = plus ? __builtin_infl () : -__builtin_infl ();
- else
- *((GFC_REAL_10*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl ("");
- break;
-#endif
-
-#if defined(HAVE_GFC_REAL_16)
-# if defined(GFC_REAL_16_IS_FLOAT128)
- case 16:
- *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, NULL);
- break;
-# else
- case 16:
- if (is_inf)
- *((GFC_REAL_16*) dest) = plus ? __builtin_infl () : -__builtin_infl ();
- else
- *((GFC_REAL_16*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl ("");
- break;
-# endif
-#endif
-
- default:
- internal_error (&dtp->common, "Unsupported real kind during IO");
- }
-
- return 0;
-}
-
-
-/* read_l()-- Read a logical value */
-
-void
-read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
-{
- char *p;
- int w;
-
- w = f->u.w;
-
- p = read_block_form (dtp, &w);
-
- if (p == NULL)
- return;
-
- while (*p == ' ')
- {
- if (--w == 0)
- goto bad;
- p++;
- }
-
- if (*p == '.')
- {
- if (--w == 0)
- goto bad;
- p++;
- }
-
- switch (*p)
- {
- case 't':
- case 'T':
- set_integer (dest, (GFC_INTEGER_LARGEST) 1, length);
- break;
- case 'f':
- case 'F':
- set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
- break;
- default:
- bad:
- generate_error (&dtp->common, LIBERROR_READ_VALUE,
- "Bad value on logical read");
- next_record (dtp, 1);
- break;
- }
-}
-
-
-static gfc_char4_t
-read_utf8 (st_parameter_dt *dtp, int *nbytes)
-{
- static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 };
- static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
- int i, nb, nread;
- gfc_char4_t c;
- char *s;
-
- *nbytes = 1;
-
- s = read_block_form (dtp, nbytes);
- if (s == NULL)
- return 0;
-
- /* If this is a short read, just return. */
- if (*nbytes == 0)
- return 0;
-
- c = (uchar) s[0];
- if (c < 0x80)
- return c;
-
- /* The number of leading 1-bits in the first byte indicates how many
- bytes follow. */
- for (nb = 2; nb < 7; nb++)
- if ((c & ~masks[nb-1]) == patns[nb-1])
- goto found;
- goto invalid;
-
- found:
- c = (c & masks[nb-1]);
- nread = nb - 1;
-
- s = read_block_form (dtp, &nread);
- if (s == NULL)
- return 0;
- /* Decode the bytes read. */
- for (i = 1; i < nb; i++)
- {
- gfc_char4_t n = *s++;
-
- if ((n & 0xC0) != 0x80)
- goto invalid;
-
- c = ((c << 6) + (n & 0x3F));
- }
-
- /* Make sure the shortest possible encoding was used. */
- if (c <= 0x7F && nb > 1) goto invalid;
- if (c <= 0x7FF && nb > 2) goto invalid;
- if (c <= 0xFFFF && nb > 3) goto invalid;
- if (c <= 0x1FFFFF && nb > 4) goto invalid;
- if (c <= 0x3FFFFFF && nb > 5) goto invalid;
-
- /* Make sure the character is valid. */
- if (c > 0x7FFFFFFF || (c >= 0xD800 && c <= 0xDFFF))
- goto invalid;
-
- return c;
-
- invalid:
- generate_error (&dtp->common, LIBERROR_READ_VALUE, "Invalid UTF-8 encoding");
- return (gfc_char4_t) '?';
-}
-
-
-static void
-read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, int width)
-{
- gfc_char4_t c;
- char *dest;
- int nbytes;
- int i, j;
-
- len = (width < len) ? len : width;
-
- dest = (char *) p;
-
- /* Proceed with decoding one character at a time. */
- for (j = 0; j < len; j++, dest++)
- {
- c = read_utf8 (dtp, &nbytes);
-
- /* Check for a short read and if so, break out. */
- if (nbytes == 0)
- break;
-
- *dest = c > 255 ? '?' : (uchar) c;
- }
-
- /* If there was a short read, pad the remaining characters. */
- for (i = j; i < len; i++)
- *dest++ = ' ';
- return;
-}
-
-static void
-read_default_char1 (st_parameter_dt *dtp, char *p, int len, int width)
-{
- char *s;
- int m, n;
-
- s = read_block_form (dtp, &width);
-
- if (s == NULL)
- return;
- if (width > len)
- s += (width - len);
-
- m = (width > len) ? len : width;
- memcpy (p, s, m);
-
- n = len - width;
- if (n > 0)
- memset (p + m, ' ', n);
-}
-
-
-static void
-read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, int width)
-{
- gfc_char4_t *dest;
- int nbytes;
- int i, j;
-
- len = (width < len) ? len : width;
-
- dest = (gfc_char4_t *) p;
-
- /* Proceed with decoding one character at a time. */
- for (j = 0; j < len; j++, dest++)
- {
- *dest = read_utf8 (dtp, &nbytes);
-
- /* Check for a short read and if so, break out. */
- if (nbytes == 0)
- break;
- }
-
- /* If there was a short read, pad the remaining characters. */
- for (i = j; i < len; i++)
- *dest++ = (gfc_char4_t) ' ';
- return;
-}
-
-
-static void
-read_default_char4 (st_parameter_dt *dtp, char *p, int len, int width)
-{
- int m, n;
- gfc_char4_t *dest;
-
- if (is_char4_unit(dtp))
- {
- gfc_char4_t *s4;
-
- s4 = (gfc_char4_t *) read_block_form4 (dtp, &width);
-
- if (s4 == NULL)
- return;
- if (width > len)
- s4 += (width - len);
-
- m = ((int) width > len) ? len : (int) width;
-
- dest = (gfc_char4_t *) p;
-
- for (n = 0; n < m; n++)
- *dest++ = *s4++;
-
- for (n = 0; n < len - (int) width; n++)
- *dest++ = (gfc_char4_t) ' ';
- }
- else
- {
- char *s;
-
- s = read_block_form (dtp, &width);
-
- if (s == NULL)
- return;
- if (width > len)
- s += (width - len);
-
- m = ((int) width > len) ? len : (int) width;
-
- dest = (gfc_char4_t *) p;
-
- for (n = 0; n < m; n++, dest++, s++)
- *dest = (unsigned char ) *s;
-
- for (n = 0; n < len - (int) width; n++, dest++)
- *dest = (unsigned char) ' ';
- }
-}
-
-
-/* read_a()-- Read a character record into a KIND=1 character destination,
- processing UTF-8 encoding if necessary. */
-
-void
-read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length)
-{
- int wi;
- int w;
-
- wi = f->u.w;
- if (wi == -1) /* '(A)' edit descriptor */
- wi = length;
- w = wi;
-
- /* Read in w characters, treating comma as not a separator. */
- dtp->u.p.sf_read_comma = 0;
-
- if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
- read_utf8_char1 (dtp, p, length, w);
- else
- read_default_char1 (dtp, p, length, w);
-
- dtp->u.p.sf_read_comma =
- dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
-}
-
-
-/* read_a_char4()-- Read a character record into a KIND=4 character destination,
- processing UTF-8 encoding if necessary. */
-
-void
-read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, int length)
-{
- int w;
-
- w = f->u.w;
- if (w == -1) /* '(A)' edit descriptor */
- w = length;
-
- /* Read in w characters, treating comma as not a separator. */
- dtp->u.p.sf_read_comma = 0;
-
- if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
- read_utf8_char4 (dtp, p, length, w);
- else
- read_default_char4 (dtp, p, length, w);
-
- dtp->u.p.sf_read_comma =
- dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
-}
-
-/* eat_leading_spaces()-- Given a character pointer and a width,
- * ignore the leading spaces. */
-
-static char *
-eat_leading_spaces (int *width, char *p)
-{
- for (;;)
- {
- if (*width == 0 || *p != ' ')
- break;
-
- (*width)--;
- p++;
- }
-
- return p;
-}
-
-
-static char
-next_char (st_parameter_dt *dtp, char **p, int *w)
-{
- char c, *q;
-
- if (*w == 0)
- return '\0';
-
- q = *p;
- c = *q++;
- *p = q;
-
- (*w)--;
-
- if (c != ' ')
- return c;
- if (dtp->u.p.blank_status != BLANK_UNSPECIFIED)
- return ' '; /* return a blank to signal a null */
-
- /* At this point, the rest of the field has to be trailing blanks */
-
- while (*w > 0)
- {
- if (*q++ != ' ')
- return '?';
- (*w)--;
- }
-
- *p = q;
- return '\0';
-}
-
-
-/* read_decimal()-- Read a decimal integer value. The values here are
- * signed values. */
-
-void
-read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
-{
- GFC_UINTEGER_LARGEST value, maxv, maxv_10;
- GFC_INTEGER_LARGEST v;
- int w, negative;
- char c, *p;
-
- w = f->u.w;
-
- p = read_block_form (dtp, &w);
-
- if (p == NULL)
- return;
-
- p = eat_leading_spaces (&w, p);
- if (w == 0)
- {
- set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
- return;
- }
-
- negative = 0;
-
- switch (*p)
- {
- case '-':
- negative = 1;
- /* Fall through */
-
- case '+':
- p++;
- if (--w == 0)
- goto bad;
- /* Fall through */
-
- default:
- break;
- }
-
- maxv = si_max (length);
- if (negative)
- maxv++;
- maxv_10 = maxv / 10;
-
- /* At this point we have a digit-string */
- value = 0;
-
- for (;;)
- {
- c = next_char (dtp, &p, &w);
- if (c == '\0')
- break;
-
- if (c == ' ')
- {
- if (dtp->u.p.blank_status == BLANK_NULL) continue;
- if (dtp->u.p.blank_status == BLANK_ZERO) c = '0';
- }
-
- if (c < '0' || c > '9')
- goto bad;
-
- if (value > maxv_10)
- goto overflow;
-
- c -= '0';
- value = 10 * value;
-
- if (value > maxv - c)
- goto overflow;
- value += c;
- }
-
- if (negative)
- v = -value;
- else
- v = value;
-
- set_integer (dest, v, length);
- return;
-
- bad:
- generate_error (&dtp->common, LIBERROR_READ_VALUE,
- "Bad value during integer read");
- next_record (dtp, 1);
- return;
-
- overflow:
- generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
- "Value overflowed during integer read");
- next_record (dtp, 1);
-
-}
-
-
-/* read_radix()-- This function reads values for non-decimal radixes.
- * The difference here is that we treat the values here as unsigned
- * values for the purposes of overflow. If minus sign is present and
- * the top bit is set, the value will be incorrect. */
-
-void
-read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
- int radix)
-{
- GFC_UINTEGER_LARGEST value, maxv, maxv_r;
- GFC_INTEGER_LARGEST v;
- int w, negative;
- char c, *p;
-
- w = f->u.w;
-
- p = read_block_form (dtp, &w);
-
- if (p == NULL)
- return;
-
- p = eat_leading_spaces (&w, p);
- if (w == 0)
- {
- set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
- return;
- }
-
- /* Maximum unsigned value, assuming two's complement. */
- maxv = 2 * si_max (length) + 1;
- maxv_r = maxv / radix;
-
- negative = 0;
- value = 0;
-
- switch (*p)
- {
- case '-':
- negative = 1;
- /* Fall through */
-
- case '+':
- p++;
- if (--w == 0)
- goto bad;
- /* Fall through */
-
- default:
- break;
- }
-
- /* At this point we have a digit-string */
- value = 0;
-
- for (;;)
- {
- c = next_char (dtp, &p, &w);
- if (c == '\0')
- break;
- if (c == ' ')
- {
- if (dtp->u.p.blank_status == BLANK_NULL) continue;
- if (dtp->u.p.blank_status == BLANK_ZERO) c = '0';
- }
-
- switch (radix)
- {
- case 2:
- if (c < '0' || c > '1')
- goto bad;
- break;
-
- case 8:
- if (c < '0' || c > '7')
- goto bad;
- break;
-
- case 16:
- switch (c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- break;
-
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- c = c - 'a' + '9' + 1;
- break;
-
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- c = c - 'A' + '9' + 1;
- break;
-
- default:
- goto bad;
- }
-
- break;
- }
-
- if (value > maxv_r)
- goto overflow;
-
- c -= '0';
- value = radix * value;
-
- if (maxv - c < value)
- goto overflow;
- value += c;
- }
-
- v = value;
- if (negative)
- v = -v;
-
- set_integer (dest, v, length);
- return;
-
- bad:
- generate_error (&dtp->common, LIBERROR_READ_VALUE,
- "Bad value during integer read");
- next_record (dtp, 1);
- return;
-
- overflow:
- generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
- "Value overflowed during integer read");
- next_record (dtp, 1);
-
-}
-
-
-/* read_f()-- Read a floating point number with F-style editing, which
- is what all of the other floating point descriptors behave as. The
- tricky part is that optional spaces are allowed after an E or D,
- and the implicit decimal point if a decimal point is not present in
- the input. */
-
-void
-read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
-{
- int w, seen_dp, exponent;
- int exponent_sign;
- const char *p;
- char *buffer;
- char *out;
- int seen_int_digit; /* Seen a digit before the decimal point? */
- int seen_dec_digit; /* Seen a digit after the decimal point? */
-
- seen_dp = 0;
- seen_int_digit = 0;
- seen_dec_digit = 0;
- exponent_sign = 1;
- exponent = 0;
- w = f->u.w;
-
- /* Read in the next block. */
- p = read_block_form (dtp, &w);
- if (p == NULL)
- return;
- p = eat_leading_spaces (&w, (char*) p);
- if (w == 0)
- goto zero;
-
- /* In this buffer we're going to re-format the number cleanly to be parsed
- by convert_real in the end; this assures we're using strtod from the
- C library for parsing and thus probably get the best accuracy possible.
- This process may add a '+0.0' in front of the number as well as change the
- exponent because of an implicit decimal point or the like. Thus allocating
- strlen ("+0.0e-1000") == 10 characters plus one for NUL more than the
- original buffer had should be enough. */
- buffer = gfc_alloca (w + 11);
- out = buffer;
-
- /* Optional sign */
- if (*p == '-' || *p == '+')
- {
- if (*p == '-')
- *(out++) = '-';
- ++p;
- --w;
- }
-
- p = eat_leading_spaces (&w, (char*) p);
- if (w == 0)
- goto zero;
-
- /* Check for Infinity or NaN. */
- if (unlikely ((w >= 3 && (*p == 'i' || *p == 'I' || *p == 'n' || *p == 'N'))))
- {
- int seen_paren = 0;
- char *save = out;
-
- /* Scan through the buffer keeping track of spaces and parenthesis. We
- null terminate the string as soon as we see a left paren or if we are
- BLANK_NULL mode. Leading spaces have already been skipped above,
- trailing spaces are ignored by converting to '\0'. A space
- between "NaN" and the optional perenthesis is not permitted. */
- while (w > 0)
- {
- *out = tolower (*p);
- switch (*p)
- {
- case ' ':
- if (dtp->u.p.blank_status == BLANK_ZERO)
- {
- *out = '0';
- break;
- }
- *out = '\0';
- if (seen_paren == 1)
- goto bad_float;
- break;
- case '(':
- seen_paren++;
- *out = '\0';
- break;
- case ')':
- if (seen_paren++ != 1)
- goto bad_float;
- break;
- default:
- if (!isalnum (*out))
- goto bad_float;
- }
- --w;
- ++p;
- ++out;
- }
-
- *out = '\0';
-
- if (seen_paren != 0 && seen_paren != 2)
- goto bad_float;
-
- if ((strcmp (save, "inf") == 0) || (strcmp (save, "infinity") == 0))
- {
- if (seen_paren)
- goto bad_float;
- }
- else if (strcmp (save, "nan") != 0)
- goto bad_float;
-
- convert_infnan (dtp, dest, buffer, length);
- return;
- }
-
- /* Process the mantissa string. */
- while (w > 0)
- {
- switch (*p)
- {
- case ',':
- if (dtp->u.p.current_unit->decimal_status != DECIMAL_COMMA)
- goto bad_float;
- /* Fall through. */
- case '.':
- if (seen_dp)
- goto bad_float;
- if (!seen_int_digit)
- *(out++) = '0';
- *(out++) = '.';
- seen_dp = 1;
- break;
-
- case ' ':
- if (dtp->u.p.blank_status == BLANK_ZERO)
- {
- *(out++) = '0';
- goto found_digit;
- }
- else if (dtp->u.p.blank_status == BLANK_NULL)
- break;
- else
- /* TODO: Should we check instead that there are only trailing
- blanks here, as is done below for exponents? */
- goto done;
- /* Fall through. */
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- *(out++) = *p;
-found_digit:
- if (!seen_dp)
- seen_int_digit = 1;
- else
- seen_dec_digit = 1;
- break;
-
- case '-':
- case '+':
- goto exponent;
-
- case 'e':
- case 'E':
- case 'd':
- case 'D':
- case 'q':
- case 'Q':
- ++p;
- --w;
- goto exponent;
-
- default:
- goto bad_float;
- }
-
- ++p;
- --w;
- }
-
- /* No exponent has been seen, so we use the current scale factor. */
- exponent = - dtp->u.p.scale_factor;
- goto done;
-
- /* At this point the start of an exponent has been found. */
-exponent:
- p = eat_leading_spaces (&w, (char*) p);
- if (*p == '-' || *p == '+')
- {
- if (*p == '-')
- exponent_sign = -1;
- ++p;
- --w;
- }
-
- /* At this point a digit string is required. We calculate the value
- of the exponent in order to take account of the scale factor and
- the d parameter before explict conversion takes place. */
-
- if (w == 0)
- goto bad_float;
-
- if (dtp->u.p.blank_status == BLANK_UNSPECIFIED)
- {
- while (w > 0 && isdigit (*p))
- {
- exponent *= 10;
- exponent += *p - '0';
- ++p;
- --w;
- }
-
- /* Only allow trailing blanks. */
- while (w > 0)
- {
- if (*p != ' ')
- goto bad_float;
- ++p;
- --w;
- }
- }
- else /* BZ or BN status is enabled. */
- {
- while (w > 0)
- {
- if (*p == ' ')
- {
- if (dtp->u.p.blank_status == BLANK_ZERO)
- exponent *= 10;
- else
- assert (dtp->u.p.blank_status == BLANK_NULL);
- }
- else if (!isdigit (*p))
- goto bad_float;
- else
- {
- exponent *= 10;
- exponent += *p - '0';
- }
-
- ++p;
- --w;
- }
- }
-
- exponent *= exponent_sign;
-
-done:
- /* Use the precision specified in the format if no decimal point has been
- seen. */
- if (!seen_dp)
- exponent -= f->u.real.d;
-
- /* Output a trailing '0' after decimal point if not yet found. */
- if (seen_dp && !seen_dec_digit)
- *(out++) = '0';
- /* Handle input of style "E+NN" by inserting a 0 for the
- significand. */
- else if (!seen_int_digit && !seen_dec_digit)
- {
- notify_std (&dtp->common, GFC_STD_LEGACY,
- "REAL input of style 'E+NN'");
- *(out++) = '0';
- }
-
- /* Print out the exponent to finish the reformatted number. Maximum 4
- digits for the exponent. */
- if (exponent != 0)
- {
- int dig;
-
- *(out++) = 'e';
- if (exponent < 0)
- {
- *(out++) = '-';
- exponent = - exponent;
- }
-
- assert (exponent < 10000);
- for (dig = 3; dig >= 0; --dig)
- {
- out[dig] = (char) ('0' + exponent % 10);
- exponent /= 10;
- }
- out += 4;
- }
- *(out++) = '\0';
-
- /* Do the actual conversion. */
- convert_real (dtp, dest, buffer, length);
-
- return;
-
- /* The value read is zero. */
-zero:
- switch (length)
- {
- case 4:
- *((GFC_REAL_4 *) dest) = 0.0;
- break;
-
- case 8:
- *((GFC_REAL_8 *) dest) = 0.0;
- break;
-
-#ifdef HAVE_GFC_REAL_10
- case 10:
- *((GFC_REAL_10 *) dest) = 0.0;
- break;
-#endif
-
-#ifdef HAVE_GFC_REAL_16
- case 16:
- *((GFC_REAL_16 *) dest) = 0.0;
- break;
-#endif
-
- default:
- internal_error (&dtp->common, "Unsupported real kind during IO");
- }
- return;
-
-bad_float:
- generate_error (&dtp->common, LIBERROR_READ_VALUE,
- "Bad value during floating point read");
- next_record (dtp, 1);
- return;
-}
-
-
-/* read_x()-- Deal with the X/TR descriptor. We just read some data
- * and never look at it. */
-
-void
-read_x (st_parameter_dt *dtp, int n)
-{
- int length, q, q2;
-
- if ((dtp->u.p.current_unit->pad_status == PAD_NO || is_internal_unit (dtp))
- && dtp->u.p.current_unit->bytes_left < n)
- n = dtp->u.p.current_unit->bytes_left;
-
- if (n == 0)
- return;
-
- length = n;
-
- if (is_internal_unit (dtp))
- {
- mem_alloc_r (dtp->u.p.current_unit->s, &length);
- if (unlikely (length < n))
- n = length;
- goto done;
- }
-
- if (dtp->u.p.sf_seen_eor)
- return;
-
- n = 0;
- while (n < length)
- {
- q = fbuf_getc (dtp->u.p.current_unit);
- if (q == EOF)
- break;
- else if (q == '\n' || q == '\r')
- {
- /* Unexpected end of line. Set the position. */
- dtp->u.p.sf_seen_eor = 1;
-
- /* If we see an EOR during non-advancing I/O, we need to skip
- the rest of the I/O statement. Set the corresponding flag. */
- if (dtp->u.p.advance_status == ADVANCE_NO || dtp->u.p.seen_dollar)
- dtp->u.p.eor_condition = 1;
-
- /* If we encounter a CR, it might be a CRLF. */
- if (q == '\r') /* Probably a CRLF */
- {
- /* See if there is an LF. */
- q2 = fbuf_getc (dtp->u.p.current_unit);
- if (q2 == '\n')
- dtp->u.p.sf_seen_eor = 2;
- else if (q2 != EOF) /* Oops, seek back. */
- fbuf_seek (dtp->u.p.current_unit, -1, SEEK_CUR);
- }
- goto done;
- }
- n++;
- }
-
- done:
- if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
- dtp->u.p.size_used += (GFC_IO_INT) n;
- dtp->u.p.current_unit->bytes_left -= n;
- dtp->u.p.current_unit->strm_pos += (gfc_offset) n;
-}
-
diff --git a/gcc-4.8.1/libgfortran/io/size_from_kind.c b/gcc-4.8.1/libgfortran/io/size_from_kind.c
deleted file mode 100644
index 8bf992eb3..000000000
--- a/gcc-4.8.1/libgfortran/io/size_from_kind.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
- Contributed by Janne Blomqvist
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-
-/* This file contains utility functions for determining the size of a
- variable given its kind. */
-
-#include "io.h"
-
-size_t
-size_from_real_kind (int kind)
-{
- switch (kind)
- {
-#ifdef HAVE_GFC_REAL_4
- case 4:
- return sizeof (GFC_REAL_4);
-#endif
-#ifdef HAVE_GFC_REAL_8
- case 8:
- return sizeof (GFC_REAL_8);
-#endif
-#ifdef HAVE_GFC_REAL_10
- case 10:
- return sizeof (GFC_REAL_10);
-#endif
-#ifdef HAVE_GFC_REAL_16
- case 16:
- return sizeof (GFC_REAL_16);
-#endif
- default:
- return kind;
- }
-}
-
-
-size_t
-size_from_complex_kind (int kind)
-{
- switch (kind)
- {
-#ifdef HAVE_GFC_COMPLEX_4
- case 4:
- return sizeof (GFC_COMPLEX_4);
-#endif
-#ifdef HAVE_GFC_COMPLEX_8
- case 8:
- return sizeof (GFC_COMPLEX_8);
-#endif
-#ifdef HAVE_GFC_COMPLEX_10
- case 10:
- return sizeof (GFC_COMPLEX_10);
-#endif
-#ifdef HAVE_GFC_COMPLEX_16
- case 16:
- return sizeof (GFC_COMPLEX_16);
-#endif
- default:
- return 2 * kind;
- }
-}
-
diff --git a/gcc-4.8.1/libgfortran/io/transfer.c b/gcc-4.8.1/libgfortran/io/transfer.c
deleted file mode 100644
index 5260be740..000000000
--- a/gcc-4.8.1/libgfortran/io/transfer.c
+++ /dev/null
@@ -1,3865 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- Namelist transfer functions contributed by Paul Thomas
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-
-/* transfer.c -- Top level handling of data transfer statements. */
-
-#include "io.h"
-#include "fbuf.h"
-#include "format.h"
-#include "unix.h"
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <errno.h>
-
-
-/* Calling conventions: Data transfer statements are unlike other
- library calls in that they extend over several calls.
-
- The first call is always a call to st_read() or st_write(). These
- subroutines return no status unless a namelist read or write is
- being done, in which case there is the usual status. No further
- calls are necessary in this case.
-
- For other sorts of data transfer, there are zero or more data
- transfer statement that depend on the format of the data transfer
- statement. For READ (and for backwards compatibily: for WRITE), one has
-
- transfer_integer
- transfer_logical
- transfer_character
- transfer_character_wide
- transfer_real
- transfer_complex
- transfer_real128
- transfer_complex128
-
- and for WRITE
-
- transfer_integer_write
- transfer_logical_write
- transfer_character_write
- transfer_character_wide_write
- transfer_real_write
- transfer_complex_write
- transfer_real128_write
- transfer_complex128_write
-
- These subroutines do not return status. The *128 functions
- are in the file transfer128.c.
-
- The last call is a call to st_[read|write]_done(). While
- something can easily go wrong with the initial st_read() or
- st_write(), an error inhibits any data from actually being
- transferred. */
-
-extern void transfer_integer (st_parameter_dt *, void *, int);
-export_proto(transfer_integer);
-
-extern void transfer_integer_write (st_parameter_dt *, void *, int);
-export_proto(transfer_integer_write);
-
-extern void transfer_real (st_parameter_dt *, void *, int);
-export_proto(transfer_real);
-
-extern void transfer_real_write (st_parameter_dt *, void *, int);
-export_proto(transfer_real_write);
-
-extern void transfer_logical (st_parameter_dt *, void *, int);
-export_proto(transfer_logical);
-
-extern void transfer_logical_write (st_parameter_dt *, void *, int);
-export_proto(transfer_logical_write);
-
-extern void transfer_character (st_parameter_dt *, void *, int);
-export_proto(transfer_character);
-
-extern void transfer_character_write (st_parameter_dt *, void *, int);
-export_proto(transfer_character_write);
-
-extern void transfer_character_wide (st_parameter_dt *, void *, int, int);
-export_proto(transfer_character_wide);
-
-extern void transfer_character_wide_write (st_parameter_dt *,
- void *, int, int);
-export_proto(transfer_character_wide_write);
-
-extern void transfer_complex (st_parameter_dt *, void *, int);
-export_proto(transfer_complex);
-
-extern void transfer_complex_write (st_parameter_dt *, void *, int);
-export_proto(transfer_complex_write);
-
-extern void transfer_array (st_parameter_dt *, gfc_array_char *, int,
- gfc_charlen_type);
-export_proto(transfer_array);
-
-extern void transfer_array_write (st_parameter_dt *, gfc_array_char *, int,
- gfc_charlen_type);
-export_proto(transfer_array_write);
-
-static void us_read (st_parameter_dt *, int);
-static void us_write (st_parameter_dt *, int);
-static void next_record_r_unf (st_parameter_dt *, int);
-static void next_record_w_unf (st_parameter_dt *, int);
-
-static const st_option advance_opt[] = {
- {"yes", ADVANCE_YES},
- {"no", ADVANCE_NO},
- {NULL, 0}
-};
-
-
-static const st_option decimal_opt[] = {
- {"point", DECIMAL_POINT},
- {"comma", DECIMAL_COMMA},
- {NULL, 0}
-};
-
-static const st_option round_opt[] = {
- {"up", ROUND_UP},
- {"down", ROUND_DOWN},
- {"zero", ROUND_ZERO},
- {"nearest", ROUND_NEAREST},
- {"compatible", ROUND_COMPATIBLE},
- {"processor_defined", ROUND_PROCDEFINED},
- {NULL, 0}
-};
-
-
-static const st_option sign_opt[] = {
- {"plus", SIGN_SP},
- {"suppress", SIGN_SS},
- {"processor_defined", SIGN_S},
- {NULL, 0}
-};
-
-static const st_option blank_opt[] = {
- {"null", BLANK_NULL},
- {"zero", BLANK_ZERO},
- {NULL, 0}
-};
-
-static const st_option delim_opt[] = {
- {"apostrophe", DELIM_APOSTROPHE},
- {"quote", DELIM_QUOTE},
- {"none", DELIM_NONE},
- {NULL, 0}
-};
-
-static const st_option pad_opt[] = {
- {"yes", PAD_YES},
- {"no", PAD_NO},
- {NULL, 0}
-};
-
-typedef enum
-{ FORMATTED_SEQUENTIAL, UNFORMATTED_SEQUENTIAL,
- FORMATTED_DIRECT, UNFORMATTED_DIRECT, FORMATTED_STREAM, UNFORMATTED_STREAM
-}
-file_mode;
-
-
-static file_mode
-current_mode (st_parameter_dt *dtp)
-{
- file_mode m;
-
- m = FORM_UNSPECIFIED;
-
- if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
- {
- m = dtp->u.p.current_unit->flags.form == FORM_FORMATTED ?
- FORMATTED_DIRECT : UNFORMATTED_DIRECT;
- }
- else if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
- {
- m = dtp->u.p.current_unit->flags.form == FORM_FORMATTED ?
- FORMATTED_SEQUENTIAL : UNFORMATTED_SEQUENTIAL;
- }
- else if (dtp->u.p.current_unit->flags.access == ACCESS_STREAM)
- {
- m = dtp->u.p.current_unit->flags.form == FORM_FORMATTED ?
- FORMATTED_STREAM : UNFORMATTED_STREAM;
- }
-
- return m;
-}
-
-
-/* Mid level data transfer statements. */
-
-/* Read sequential file - internal unit */
-
-static char *
-read_sf_internal (st_parameter_dt *dtp, int * length)
-{
- static char *empty_string[0];
- char *base;
- int lorig;
-
- /* Zero size array gives internal unit len of 0. Nothing to read. */
- if (dtp->internal_unit_len == 0
- && dtp->u.p.current_unit->pad_status == PAD_NO)
- hit_eof (dtp);
-
- /* If we have seen an eor previously, return a length of 0. The
- caller is responsible for correctly padding the input field. */
- if (dtp->u.p.sf_seen_eor)
- {
- *length = 0;
- /* Just return something that isn't a NULL pointer, otherwise the
- caller thinks an error occured. */
- return (char*) empty_string;
- }
-
- lorig = *length;
- if (is_char4_unit(dtp))
- {
- int i;
- gfc_char4_t *p = (gfc_char4_t *) mem_alloc_r4 (dtp->u.p.current_unit->s,
- length);
- base = fbuf_alloc (dtp->u.p.current_unit, lorig);
- for (i = 0; i < *length; i++, p++)
- base[i] = *p > 255 ? '?' : (unsigned char) *p;
- }
- else
- base = mem_alloc_r (dtp->u.p.current_unit->s, length);
-
- if (unlikely (lorig > *length))
- {
- hit_eof (dtp);
- return NULL;
- }
-
- dtp->u.p.current_unit->bytes_left -= *length;
-
- if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
- dtp->u.p.size_used += (GFC_IO_INT) *length;
-
- return base;
-
-}
-
-/* When reading sequential formatted records we have a problem. We
- don't know how long the line is until we read the trailing newline,
- and we don't want to read too much. If we read too much, we might
- have to do a physical seek backwards depending on how much data is
- present, and devices like terminals aren't seekable and would cause
- an I/O error.
-
- Given this, the solution is to read a byte at a time, stopping if
- we hit the newline. For small allocations, we use a static buffer.
- For larger allocations, we are forced to allocate memory on the
- heap. Hopefully this won't happen very often. */
-
-/* Read sequential file - external unit */
-
-static char *
-read_sf (st_parameter_dt *dtp, int * length)
-{
- static char *empty_string[0];
- int q, q2;
- int n, lorig, seen_comma;
-
- /* If we have seen an eor previously, return a length of 0. The
- caller is responsible for correctly padding the input field. */
- if (dtp->u.p.sf_seen_eor)
- {
- *length = 0;
- /* Just return something that isn't a NULL pointer, otherwise the
- caller thinks an error occured. */
- return (char*) empty_string;
- }
-
- n = seen_comma = 0;
-
- /* Read data into format buffer and scan through it. */
- lorig = *length;
-
- while (n < *length)
- {
- q = fbuf_getc (dtp->u.p.current_unit);
- if (q == EOF)
- break;
- else if (q == '\n' || q == '\r')
- {
- /* Unexpected end of line. Set the position. */
- dtp->u.p.sf_seen_eor = 1;
-
- /* If we see an EOR during non-advancing I/O, we need to skip
- the rest of the I/O statement. Set the corresponding flag. */
- if (dtp->u.p.advance_status == ADVANCE_NO || dtp->u.p.seen_dollar)
- dtp->u.p.eor_condition = 1;
-
- /* If we encounter a CR, it might be a CRLF. */
- if (q == '\r') /* Probably a CRLF */
- {
- /* See if there is an LF. */
- q2 = fbuf_getc (dtp->u.p.current_unit);
- if (q2 == '\n')
- dtp->u.p.sf_seen_eor = 2;
- else if (q2 != EOF) /* Oops, seek back. */
- fbuf_seek (dtp->u.p.current_unit, -1, SEEK_CUR);
- }
-
- /* Without padding, terminate the I/O statement without assigning
- the value. With padding, the value still needs to be assigned,
- so we can just continue with a short read. */
- if (dtp->u.p.current_unit->pad_status == PAD_NO)
- {
- generate_error (&dtp->common, LIBERROR_EOR, NULL);
- return NULL;
- }
-
- *length = n;
- goto done;
- }
- /* 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
- strings are not ignored */
- else if (q == ',')
- if (dtp->u.p.sf_read_comma == 1)
- {
- seen_comma = 1;
- notify_std (&dtp->common, GFC_STD_GNU,
- "Comma in formatted numeric read.");
- break;
- }
- n++;
- }
-
- *length = n;
-
- /* A short read implies we hit EOF, unless we hit EOR, a comma, or
- some other stuff. Set the relevant flags. */
- if (lorig > *length && !dtp->u.p.sf_seen_eor && !seen_comma)
- {
- if (n > 0)
- {
- if (dtp->u.p.advance_status == ADVANCE_NO)
- {
- if (dtp->u.p.current_unit->pad_status == PAD_NO)
- {
- hit_eof (dtp);
- return NULL;
- }
- else
- dtp->u.p.eor_condition = 1;
- }
- else
- dtp->u.p.at_eof = 1;
- }
- else if (dtp->u.p.advance_status == ADVANCE_NO
- || dtp->u.p.current_unit->pad_status == PAD_NO
- || dtp->u.p.current_unit->bytes_left
- == dtp->u.p.current_unit->recl)
- {
- hit_eof (dtp);
- return NULL;
- }
- }
-
- done:
-
- dtp->u.p.current_unit->bytes_left -= n;
-
- if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
- dtp->u.p.size_used += (GFC_IO_INT) n;
-
- /* We can't call fbuf_getptr before the loop doing fbuf_getc, because
- fbuf_getc might reallocate the buffer. So return current pointer
- minus all the advances, which is n plus up to two characters
- of newline or comma. */
- return fbuf_getptr (dtp->u.p.current_unit)
- - n - dtp->u.p.sf_seen_eor - seen_comma;
-}
-
-
-/* Function for reading the next couple of bytes from the current
- file, advancing the current position. We return FAILURE on end of record or
- end of file. This function is only for formatted I/O, unformatted uses
- read_block_direct.
-
- 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
- opened with PAD=YES. The caller must assume tailing spaces for
- short reads. */
-
-void *
-read_block_form (st_parameter_dt *dtp, int * nbytes)
-{
- char *source;
- int norig;
-
- if (!is_stream_io (dtp))
- {
- if (dtp->u.p.current_unit->bytes_left < (gfc_offset) *nbytes)
- {
- /* For preconnected units with default record length, set bytes left
- to unit record length and proceed, otherwise error. */
- if (dtp->u.p.current_unit->unit_number == options.stdin_unit
- && dtp->u.p.current_unit->recl == DEFAULT_RECL)
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
- else
- {
- if (unlikely (dtp->u.p.current_unit->pad_status == PAD_NO)
- && !is_internal_unit (dtp))
- {
- /* Not enough data left. */
- generate_error (&dtp->common, LIBERROR_EOR, NULL);
- return NULL;
- }
- }
-
- if (unlikely (dtp->u.p.current_unit->bytes_left == 0
- && !is_internal_unit(dtp)))
- {
- hit_eof (dtp);
- return NULL;
- }
-
- *nbytes = dtp->u.p.current_unit->bytes_left;
- }
- }
-
- if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED &&
- (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL ||
- dtp->u.p.current_unit->flags.access == ACCESS_STREAM))
- {
- if (is_internal_unit (dtp))
- source = read_sf_internal (dtp, nbytes);
- else
- source = read_sf (dtp, nbytes);
-
- dtp->u.p.current_unit->strm_pos +=
- (gfc_offset) (*nbytes + dtp->u.p.sf_seen_eor);
- return source;
- }
-
- /* If we reach here, we can assume it's direct access. */
-
- dtp->u.p.current_unit->bytes_left -= (gfc_offset) *nbytes;
-
- norig = *nbytes;
- source = fbuf_read (dtp->u.p.current_unit, nbytes);
- fbuf_seek (dtp->u.p.current_unit, *nbytes, SEEK_CUR);
-
- if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
- dtp->u.p.size_used += (GFC_IO_INT) *nbytes;
-
- if (norig != *nbytes)
- {
- /* Short read, this shouldn't happen. */
- if (!dtp->u.p.current_unit->pad_status == PAD_YES)
- {
- generate_error (&dtp->common, LIBERROR_EOR, NULL);
- source = NULL;
- }
- }
-
- dtp->u.p.current_unit->strm_pos += (gfc_offset) *nbytes;
-
- return source;
-}
-
-
-/* Read a block from a character(kind=4) internal unit, to be transferred into
- a character(kind=4) variable. Note: Portions of this code borrowed from
- read_sf_internal. */
-void *
-read_block_form4 (st_parameter_dt *dtp, int * nbytes)
-{
- static gfc_char4_t *empty_string[0];
- gfc_char4_t *source;
- int lorig;
-
- if (dtp->u.p.current_unit->bytes_left < (gfc_offset) *nbytes)
- *nbytes = dtp->u.p.current_unit->bytes_left;
-
- /* Zero size array gives internal unit len of 0. Nothing to read. */
- if (dtp->internal_unit_len == 0
- && dtp->u.p.current_unit->pad_status == PAD_NO)
- hit_eof (dtp);
-
- /* If we have seen an eor previously, return a length of 0. The
- caller is responsible for correctly padding the input field. */
- if (dtp->u.p.sf_seen_eor)
- {
- *nbytes = 0;
- /* Just return something that isn't a NULL pointer, otherwise the
- caller thinks an error occured. */
- return empty_string;
- }
-
- lorig = *nbytes;
- source = (gfc_char4_t *) mem_alloc_r4 (dtp->u.p.current_unit->s, nbytes);
-
- if (unlikely (lorig > *nbytes))
- {
- hit_eof (dtp);
- return NULL;
- }
-
- dtp->u.p.current_unit->bytes_left -= *nbytes;
-
- if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
- dtp->u.p.size_used += (GFC_IO_INT) *nbytes;
-
- return source;
-}
-
-
-/* Reads a block directly into application data space. This is for
- unformatted files. */
-
-static void
-read_block_direct (st_parameter_dt *dtp, void *buf, size_t nbytes)
-{
- ssize_t to_read_record;
- ssize_t have_read_record;
- ssize_t to_read_subrecord;
- ssize_t have_read_subrecord;
- int short_record;
-
- if (is_stream_io (dtp))
- {
- have_read_record = sread (dtp->u.p.current_unit->s, buf,
- nbytes);
- if (unlikely (have_read_record < 0))
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
-
- dtp->u.p.current_unit->strm_pos += (gfc_offset) have_read_record;
-
- if (unlikely ((ssize_t) nbytes != have_read_record))
- {
- /* Short read, e.g. if we hit EOF. For stream files,
- we have to set the end-of-file condition. */
- hit_eof (dtp);
- }
- return;
- }
-
- if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
- {
- if (dtp->u.p.current_unit->bytes_left < (gfc_offset) nbytes)
- {
- short_record = 1;
- to_read_record = dtp->u.p.current_unit->bytes_left;
- nbytes = to_read_record;
- }
- else
- {
- short_record = 0;
- to_read_record = nbytes;
- }
-
- dtp->u.p.current_unit->bytes_left -= to_read_record;
-
- to_read_record = sread (dtp->u.p.current_unit->s, buf, to_read_record);
- if (unlikely (to_read_record < 0))
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
-
- if (to_read_record != (ssize_t) nbytes)
- {
- /* Short read, e.g. if we hit EOF. Apparently, we read
- more than was written to the last record. */
- return;
- }
-
- if (unlikely (short_record))
- {
- generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL);
- }
- return;
- }
-
- /* Unformatted sequential. We loop over the subrecords, reading
- until the request has been fulfilled or the record has run out
- of continuation subrecords. */
-
- /* Check whether we exceed the total record length. */
-
- if (dtp->u.p.current_unit->flags.has_recl
- && ((gfc_offset) nbytes > dtp->u.p.current_unit->bytes_left))
- {
- to_read_record = dtp->u.p.current_unit->bytes_left;
- short_record = 1;
- }
- else
- {
- to_read_record = nbytes;
- short_record = 0;
- }
- have_read_record = 0;
-
- while(1)
- {
- if (dtp->u.p.current_unit->bytes_left_subrecord
- < (gfc_offset) to_read_record)
- {
- to_read_subrecord = dtp->u.p.current_unit->bytes_left_subrecord;
- to_read_record -= to_read_subrecord;
- }
- else
- {
- to_read_subrecord = to_read_record;
- to_read_record = 0;
- }
-
- dtp->u.p.current_unit->bytes_left_subrecord -= to_read_subrecord;
-
- have_read_subrecord = sread (dtp->u.p.current_unit->s,
- buf + have_read_record, to_read_subrecord);
- if (unlikely (have_read_subrecord < 0))
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
-
- have_read_record += have_read_subrecord;
-
- if (unlikely (to_read_subrecord != have_read_subrecord))
- {
- /* Short read, e.g. if we hit EOF. This means the record
- structure has been corrupted, or the trailing record
- marker would still be present. */
-
- generate_error (&dtp->common, LIBERROR_CORRUPT_FILE, NULL);
- return;
- }
-
- if (to_read_record > 0)
- {
- if (likely (dtp->u.p.current_unit->continued))
- {
- next_record_r_unf (dtp, 0);
- us_read (dtp, 1);
- }
- else
- {
- /* Let's make sure the file position is correctly pre-positioned
- for the next read statement. */
-
- dtp->u.p.current_unit->current_record = 0;
- next_record_r_unf (dtp, 0);
- generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL);
- return;
- }
- }
- else
- {
- /* Normal exit, the read request has been fulfilled. */
- break;
- }
- }
-
- dtp->u.p.current_unit->bytes_left -= have_read_record;
- if (unlikely (short_record))
- {
- generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL);
- return;
- }
- return;
-}
-
-
-/* Function for writing a block of bytes to the current file at the
- current position, advancing the file pointer. We are given a length
- and return a pointer to a buffer that the caller must (completely)
- fill in. Returns NULL on error. */
-
-void *
-write_block (st_parameter_dt *dtp, int length)
-{
- char *dest;
-
- if (!is_stream_io (dtp))
- {
- if (dtp->u.p.current_unit->bytes_left < (gfc_offset) length)
- {
- /* For preconnected units with default record length, set bytes left
- to unit record length and proceed, otherwise error. */
- if (likely ((dtp->u.p.current_unit->unit_number
- == options.stdout_unit
- || dtp->u.p.current_unit->unit_number
- == options.stderr_unit)
- && dtp->u.p.current_unit->recl == DEFAULT_RECL))
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
- else
- {
- generate_error (&dtp->common, LIBERROR_EOR, NULL);
- return NULL;
- }
- }
-
- dtp->u.p.current_unit->bytes_left -= (gfc_offset) length;
- }
-
- if (is_internal_unit (dtp))
- {
- if (dtp->common.unit) /* char4 internel unit. */
- {
- gfc_char4_t *dest4;
- dest4 = mem_alloc_w4 (dtp->u.p.current_unit->s, &length);
- if (dest4 == NULL)
- {
- generate_error (&dtp->common, LIBERROR_END, NULL);
- return NULL;
- }
- return dest4;
- }
- else
- dest = mem_alloc_w (dtp->u.p.current_unit->s, &length);
-
- if (dest == NULL)
- {
- generate_error (&dtp->common, LIBERROR_END, NULL);
- return NULL;
- }
-
- if (unlikely (dtp->u.p.current_unit->endfile == AT_ENDFILE))
- generate_error (&dtp->common, LIBERROR_END, NULL);
- }
- else
- {
- 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)
- dtp->u.p.size_used += (GFC_IO_INT) length;
-
- dtp->u.p.current_unit->strm_pos += (gfc_offset) length;
-
- return dest;
-}
-
-
-/* High level interface to swrite(), taking care of errors. This is only
- called for unformatted files. There are three cases to consider:
- Stream I/O, unformatted direct, unformatted sequential. */
-
-static try
-write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes)
-{
-
- ssize_t have_written;
- ssize_t to_write_subrecord;
- int short_record;
-
- /* Stream I/O. */
-
- if (is_stream_io (dtp))
- {
- have_written = swrite (dtp->u.p.current_unit->s, buf, nbytes);
- if (unlikely (have_written < 0))
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return FAILURE;
- }
-
- dtp->u.p.current_unit->strm_pos += (gfc_offset) have_written;
-
- return SUCCESS;
- }
-
- /* Unformatted direct access. */
-
- if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
- {
- if (unlikely (dtp->u.p.current_unit->bytes_left < (gfc_offset) nbytes))
- {
- generate_error (&dtp->common, LIBERROR_DIRECT_EOR, NULL);
- return FAILURE;
- }
-
- if (buf == NULL && nbytes == 0)
- return SUCCESS;
-
- have_written = swrite (dtp->u.p.current_unit->s, buf, nbytes);
- if (unlikely (have_written < 0))
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return FAILURE;
- }
-
- dtp->u.p.current_unit->strm_pos += (gfc_offset) have_written;
- dtp->u.p.current_unit->bytes_left -= (gfc_offset) have_written;
-
- return SUCCESS;
- }
-
- /* Unformatted sequential. */
-
- have_written = 0;
-
- if (dtp->u.p.current_unit->flags.has_recl
- && (gfc_offset) nbytes > dtp->u.p.current_unit->bytes_left)
- {
- nbytes = dtp->u.p.current_unit->bytes_left;
- short_record = 1;
- }
- else
- {
- short_record = 0;
- }
-
- while (1)
- {
-
- to_write_subrecord =
- (size_t) dtp->u.p.current_unit->bytes_left_subrecord < nbytes ?
- (size_t) dtp->u.p.current_unit->bytes_left_subrecord : nbytes;
-
- dtp->u.p.current_unit->bytes_left_subrecord -=
- (gfc_offset) to_write_subrecord;
-
- to_write_subrecord = swrite (dtp->u.p.current_unit->s,
- buf + have_written, to_write_subrecord);
- if (unlikely (to_write_subrecord < 0))
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return FAILURE;
- }
-
- dtp->u.p.current_unit->strm_pos += (gfc_offset) to_write_subrecord;
- nbytes -= to_write_subrecord;
- have_written += to_write_subrecord;
-
- if (nbytes == 0)
- break;
-
- next_record_w_unf (dtp, 1);
- us_write (dtp, 1);
- }
- dtp->u.p.current_unit->bytes_left -= have_written;
- if (unlikely (short_record))
- {
- generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL);
- return FAILURE;
- }
- return SUCCESS;
-}
-
-
-/* Reverse memcpy - used for byte swapping. */
-
-static void
-reverse_memcpy (void *dest, const void *src, size_t n)
-{
- char *d, *s;
- size_t i;
-
- d = (char *) dest;
- s = (char *) src + n - 1;
-
- /* Write with ascending order - this is likely faster
- on modern architectures because of write combining. */
- for (i=0; i<n; i++)
- *(d++) = *(s--);
-}
-
-
-/* Utility function for byteswapping an array, using the bswap
- builtins if possible. dest and src can overlap completely, or then
- they must point to separate objects; partial overlaps are not
- allowed. */
-
-static void
-bswap_array (void *dest, const void *src, size_t size, size_t nelems)
-{
- const char *ps;
- char *pd;
-
- switch (size)
- {
- case 1:
- break;
- case 2:
- for (size_t i = 0; i < nelems; i++)
- ((uint16_t*)dest)[i] = __builtin_bswap16 (((uint16_t*)src)[i]);
- break;
- case 4:
- for (size_t i = 0; i < nelems; i++)
- ((uint32_t*)dest)[i] = __builtin_bswap32 (((uint32_t*)src)[i]);
- break;
- case 8:
- for (size_t i = 0; i < nelems; i++)
- ((uint64_t*)dest)[i] = __builtin_bswap64 (((uint64_t*)src)[i]);
- break;
- case 12:
- ps = src;
- pd = dest;
- for (size_t i = 0; i < nelems; i++)
- {
- uint32_t tmp;
- memcpy (&tmp, ps, 4);
- *(uint32_t*)pd = __builtin_bswap32 (*(uint32_t*)(ps + 8));
- *(uint32_t*)(pd + 4) = __builtin_bswap32 (*(uint32_t*)(ps + 4));
- *(uint32_t*)(pd + 8) = __builtin_bswap32 (tmp);
- ps += size;
- pd += size;
- }
- break;
- case 16:
- ps = src;
- pd = dest;
- for (size_t i = 0; i < nelems; i++)
- {
- uint64_t tmp;
- memcpy (&tmp, ps, 8);
- *(uint64_t*)pd = __builtin_bswap64 (*(uint64_t*)(ps + 8));
- *(uint64_t*)(pd + 8) = __builtin_bswap64 (tmp);
- ps += size;
- pd += size;
- }
- break;
- default:
- pd = dest;
- if (dest != src)
- {
- ps = src;
- for (size_t i = 0; i < nelems; i++)
- {
- reverse_memcpy (pd, ps, size);
- ps += size;
- pd += size;
- }
- }
- else
- {
- /* In-place byte swap. */
- for (size_t i = 0; i < nelems; i++)
- {
- char tmp, *low = pd, *high = pd + size - 1;
- for (size_t j = 0; j < size/2; j++)
- {
- tmp = *low;
- *low = *high;
- *high = tmp;
- low++;
- high--;
- }
- pd += size;
- }
- }
- }
-}
-
-
-/* Master function for unformatted reads. */
-
-static void
-unformatted_read (st_parameter_dt *dtp, bt type,
- void *dest, int kind, size_t size, size_t nelems)
-{
- if (type == BT_CHARACTER)
- size *= GFC_SIZE_OF_CHAR_KIND(kind);
- read_block_direct (dtp, dest, size * nelems);
-
- if (unlikely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_SWAP)
- && kind != 1)
- {
- /* Handle wide chracters. */
- if (type == BT_CHARACTER)
- {
- nelems *= size;
- size = kind;
- }
-
- /* Break up complex into its constituent reals. */
- else if (type == BT_COMPLEX)
- {
- nelems *= 2;
- size /= 2;
- }
- bswap_array (dest, dest, size, nelems);
- }
-}
-
-
-/* Master function for unformatted writes. NOTE: For kind=10 the size is 16
- bytes on 64 bit machines. The unused bytes are not initialized and never
- used, which can show an error with memory checking analyzers like
- valgrind. */
-
-static void
-unformatted_write (st_parameter_dt *dtp, bt type,
- void *source, int kind, size_t size, size_t nelems)
-{
- if (likely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE)
- || kind == 1)
- {
- size_t stride = type == BT_CHARACTER ?
- size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
-
- write_buf (dtp, source, stride * nelems);
- }
- else
- {
-#define BSWAP_BUFSZ 512
- char buffer[BSWAP_BUFSZ];
- char *p;
- size_t nrem;
-
- p = source;
-
- /* Handle wide chracters. */
- if (type == BT_CHARACTER && kind != 1)
- {
- nelems *= size;
- size = kind;
- }
-
- /* Break up complex into its constituent reals. */
- if (type == BT_COMPLEX)
- {
- nelems *= 2;
- size /= 2;
- }
-
- /* By now, all complex variables have been split into their
- constituent reals. */
-
- nrem = nelems;
- do
- {
- size_t nc;
- if (size * nrem > BSWAP_BUFSZ)
- nc = BSWAP_BUFSZ / size;
- else
- nc = nrem;
-
- bswap_array (buffer, p, size, nc);
- write_buf (dtp, buffer, size * nc);
- p += size * nc;
- nrem -= nc;
- }
- while (nrem > 0);
- }
-}
-
-
-/* Return a pointer to the name of a type. */
-
-const char *
-type_name (bt type)
-{
- const char *p;
-
- switch (type)
- {
- case BT_INTEGER:
- p = "INTEGER";
- break;
- case BT_LOGICAL:
- p = "LOGICAL";
- break;
- case BT_CHARACTER:
- p = "CHARACTER";
- break;
- case BT_REAL:
- p = "REAL";
- break;
- case BT_COMPLEX:
- p = "COMPLEX";
- break;
- default:
- internal_error (NULL, "type_name(): Bad type");
- }
-
- return p;
-}
-
-
-/* Write a constant string to the output.
- This is complicated because the string can have doubled delimiters
- in it. The length in the format node is the true length. */
-
-static void
-write_constant_string (st_parameter_dt *dtp, const fnode *f)
-{
- char c, delimiter, *p, *q;
- int length;
-
- length = f->u.string.length;
- if (length == 0)
- return;
-
- p = write_block (dtp, length);
- if (p == NULL)
- return;
-
- q = f->u.string.p;
- delimiter = q[-1];
-
- for (; length > 0; length--)
- {
- c = *p++ = *q++;
- if (c == delimiter && c != 'H' && c != 'h')
- q++; /* Skip the doubled delimiter. */
- }
-}
-
-
-/* Given actual and expected types in a formatted data transfer, make
- sure they agree. If not, an error message is generated. Returns
- nonzero if something went wrong. */
-
-static int
-require_type (st_parameter_dt *dtp, bt expected, bt actual, const fnode *f)
-{
-#define BUFLEN 100
- char buffer[BUFLEN];
-
- if (actual == expected)
- return 0;
-
- /* Adjust item_count before emitting error message. */
- snprintf (buffer, BUFLEN,
- "Expected %s for item %d in formatted transfer, got %s",
- type_name (expected), dtp->u.p.item_count - 1, type_name (actual));
-
- format_error (dtp, f, buffer);
- return 1;
-}
-
-
-static int
-require_numeric_type (st_parameter_dt *dtp, bt actual, const fnode *f)
-{
-#define BUFLEN 100
- char buffer[BUFLEN];
-
- if (actual == BT_INTEGER || actual == BT_REAL || actual == BT_COMPLEX)
- return 0;
-
- /* Adjust item_count before emitting error message. */
- snprintf (buffer, BUFLEN,
- "Expected numeric type for item %d in formatted transfer, got %s",
- dtp->u.p.item_count - 1, type_name (actual));
-
- format_error (dtp, f, buffer);
- return 1;
-}
-
-
-/* This function is in the main loop for a formatted data transfer
- statement. It would be natural to implement this as a coroutine
- with the user program, but C makes that awkward. We loop,
- processing format elements. When we actually have to transfer
- data instead of just setting flags, we return control to the user
- program which calls a function that supplies the address and type
- of the next element, then comes back here to process it. */
-
-static void
-formatted_transfer_scalar_read (st_parameter_dt *dtp, bt type, void *p, int kind,
- size_t size)
-{
- int pos, bytes_used;
- const fnode *f;
- format_token t;
- int n;
- int consume_data_flag;
-
- /* Change a complex data item into a pair of reals. */
-
- n = (p == NULL) ? 0 : ((type != BT_COMPLEX) ? 1 : 2);
- if (type == BT_COMPLEX)
- {
- type = BT_REAL;
- size /= 2;
- }
-
- /* If there's an EOR condition, we simulate finalizing the transfer
- by doing nothing. */
- if (dtp->u.p.eor_condition)
- return;
-
- /* Set this flag so that commas in reads cause the read to complete before
- the entire field has been read. The next read field will start right after
- the comma in the stream. (Set to 0 for character reads). */
- dtp->u.p.sf_read_comma =
- dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
-
- for (;;)
- {
- /* If reversion has occurred and there is another real data item,
- then we have to move to the next record. */
- if (dtp->u.p.reversion_flag && n > 0)
- {
- dtp->u.p.reversion_flag = 0;
- next_record (dtp, 0);
- }
-
- consume_data_flag = 1;
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- break;
-
- f = next_format (dtp);
- if (f == NULL)
- {
- /* No data descriptors left. */
- if (unlikely (n > 0))
- generate_error (&dtp->common, LIBERROR_FORMAT,
- "Insufficient data descriptors in format after reversion");
- return;
- }
-
- t = f->format;
-
- bytes_used = (int)(dtp->u.p.current_unit->recl
- - dtp->u.p.current_unit->bytes_left);
-
- if (is_stream_io(dtp))
- bytes_used = 0;
-
- switch (t)
- {
- case FMT_I:
- if (n == 0)
- goto need_read_data;
- if (require_type (dtp, BT_INTEGER, type, f))
- return;
- read_decimal (dtp, f, p, kind);
- break;
-
- case FMT_B:
- if (n == 0)
- goto need_read_data;
- if (!(compile_options.allow_std & GFC_STD_GNU)
- && require_numeric_type (dtp, type, f))
- return;
- if (!(compile_options.allow_std & GFC_STD_F2008)
- && require_type (dtp, BT_INTEGER, type, f))
- return;
- read_radix (dtp, f, p, kind, 2);
- break;
-
- case FMT_O:
- if (n == 0)
- goto need_read_data;
- if (!(compile_options.allow_std & GFC_STD_GNU)
- && require_numeric_type (dtp, type, f))
- return;
- if (!(compile_options.allow_std & GFC_STD_F2008)
- && require_type (dtp, BT_INTEGER, type, f))
- return;
- read_radix (dtp, f, p, kind, 8);
- break;
-
- case FMT_Z:
- if (n == 0)
- goto need_read_data;
- if (!(compile_options.allow_std & GFC_STD_GNU)
- && require_numeric_type (dtp, type, f))
- return;
- if (!(compile_options.allow_std & GFC_STD_F2008)
- && require_type (dtp, BT_INTEGER, type, f))
- return;
- read_radix (dtp, f, p, kind, 16);
- break;
-
- case FMT_A:
- if (n == 0)
- goto need_read_data;
-
- /* It is possible to have FMT_A with something not BT_CHARACTER such
- as when writing out hollerith strings, so check both type
- and kind before calling wide character routines. */
- if (type == BT_CHARACTER && kind == 4)
- read_a_char4 (dtp, f, p, size);
- else
- read_a (dtp, f, p, size);
- break;
-
- case FMT_L:
- if (n == 0)
- goto need_read_data;
- read_l (dtp, f, p, kind);
- break;
-
- case FMT_D:
- if (n == 0)
- goto need_read_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- read_f (dtp, f, p, kind);
- break;
-
- case FMT_E:
- if (n == 0)
- goto need_read_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- read_f (dtp, f, p, kind);
- break;
-
- case FMT_EN:
- if (n == 0)
- goto need_read_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- read_f (dtp, f, p, kind);
- break;
-
- case FMT_ES:
- if (n == 0)
- goto need_read_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- read_f (dtp, f, p, kind);
- break;
-
- case FMT_F:
- if (n == 0)
- goto need_read_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- read_f (dtp, f, p, kind);
- break;
-
- case FMT_G:
- if (n == 0)
- goto need_read_data;
- switch (type)
- {
- case BT_INTEGER:
- read_decimal (dtp, f, p, kind);
- break;
- case BT_LOGICAL:
- read_l (dtp, f, p, kind);
- break;
- case BT_CHARACTER:
- if (kind == 4)
- read_a_char4 (dtp, f, p, size);
- else
- read_a (dtp, f, p, size);
- break;
- case BT_REAL:
- read_f (dtp, f, p, kind);
- break;
- default:
- internal_error (&dtp->common, "formatted_transfer(): Bad type");
- }
- break;
-
- case FMT_STRING:
- consume_data_flag = 0;
- format_error (dtp, f, "Constant string in input format");
- return;
-
- /* Format codes that don't transfer data. */
- case FMT_X:
- case FMT_TR:
- consume_data_flag = 0;
- dtp->u.p.skips += f->u.n;
- pos = bytes_used + dtp->u.p.skips - 1;
- dtp->u.p.pending_spaces = pos - dtp->u.p.max_pos + 1;
- read_x (dtp, f->u.n);
- break;
-
- case FMT_TL:
- case FMT_T:
- consume_data_flag = 0;
-
- if (f->format == FMT_TL)
- {
- /* Handle the special case when no bytes have been used yet.
- Cannot go below zero. */
- if (bytes_used == 0)
- {
- dtp->u.p.pending_spaces -= f->u.n;
- dtp->u.p.skips -= f->u.n;
- dtp->u.p.skips = dtp->u.p.skips < 0 ? 0 : dtp->u.p.skips;
- }
-
- pos = bytes_used - f->u.n;
- }
- else /* FMT_T */
- pos = f->u.n - 1;
-
- /* Standard 10.6.1.1: excessive left tabbing is reset to the
- left tab limit. We do not check if the position has gone
- beyond the end of record because a subsequent tab could
- bring us back again. */
- pos = pos < 0 ? 0 : pos;
-
- dtp->u.p.skips = dtp->u.p.skips + pos - bytes_used;
- dtp->u.p.pending_spaces = dtp->u.p.pending_spaces
- + pos - dtp->u.p.max_pos;
- dtp->u.p.pending_spaces = dtp->u.p.pending_spaces < 0
- ? 0 : dtp->u.p.pending_spaces;
- if (dtp->u.p.skips == 0)
- break;
-
- /* Adjust everything for end-of-record condition */
- if (dtp->u.p.sf_seen_eor && !is_internal_unit (dtp))
- {
- dtp->u.p.current_unit->bytes_left -= dtp->u.p.sf_seen_eor;
- dtp->u.p.skips -= dtp->u.p.sf_seen_eor;
- bytes_used = pos;
- dtp->u.p.sf_seen_eor = 0;
- }
- if (dtp->u.p.skips < 0)
- {
- if (is_internal_unit (dtp))
- sseek (dtp->u.p.current_unit->s, dtp->u.p.skips, SEEK_CUR);
- else
- fbuf_seek (dtp->u.p.current_unit, dtp->u.p.skips, SEEK_CUR);
- dtp->u.p.current_unit->bytes_left -= (gfc_offset) dtp->u.p.skips;
- dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
- }
- else
- read_x (dtp, dtp->u.p.skips);
- break;
-
- case FMT_S:
- consume_data_flag = 0;
- dtp->u.p.sign_status = SIGN_S;
- break;
-
- case FMT_SS:
- consume_data_flag = 0;
- dtp->u.p.sign_status = SIGN_SS;
- break;
-
- case FMT_SP:
- consume_data_flag = 0;
- dtp->u.p.sign_status = SIGN_SP;
- break;
-
- case FMT_BN:
- consume_data_flag = 0 ;
- dtp->u.p.blank_status = BLANK_NULL;
- break;
-
- case FMT_BZ:
- consume_data_flag = 0;
- dtp->u.p.blank_status = BLANK_ZERO;
- break;
-
- case FMT_DC:
- consume_data_flag = 0;
- dtp->u.p.current_unit->decimal_status = DECIMAL_COMMA;
- break;
-
- case FMT_DP:
- consume_data_flag = 0;
- dtp->u.p.current_unit->decimal_status = DECIMAL_POINT;
- break;
-
- case FMT_RC:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_COMPATIBLE;
- break;
-
- case FMT_RD:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_DOWN;
- break;
-
- case FMT_RN:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_NEAREST;
- break;
-
- case FMT_RP:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_PROCDEFINED;
- break;
-
- case FMT_RU:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_UP;
- break;
-
- case FMT_RZ:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_ZERO;
- break;
-
- case FMT_P:
- consume_data_flag = 0;
- dtp->u.p.scale_factor = f->u.k;
- break;
-
- case FMT_DOLLAR:
- consume_data_flag = 0;
- dtp->u.p.seen_dollar = 1;
- break;
-
- case FMT_SLASH:
- consume_data_flag = 0;
- dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
- next_record (dtp, 0);
- break;
-
- case FMT_COLON:
- /* A colon descriptor causes us to exit this loop (in
- particular preventing another / descriptor from being
- processed) unless there is another data item to be
- transferred. */
- consume_data_flag = 0;
- if (n == 0)
- return;
- break;
-
- default:
- internal_error (&dtp->common, "Bad format node");
- }
-
- /* Adjust the item count and data pointer. */
-
- if ((consume_data_flag > 0) && (n > 0))
- {
- n--;
- p = ((char *) p) + size;
- }
-
- dtp->u.p.skips = 0;
-
- pos = (int)(dtp->u.p.current_unit->recl - dtp->u.p.current_unit->bytes_left);
- dtp->u.p.max_pos = (dtp->u.p.max_pos > pos) ? dtp->u.p.max_pos : pos;
- }
-
- return;
-
- /* Come here when we need a data descriptor but don't have one. We
- push the current format node back onto the input, then return and
- let the user program call us back with the data. */
- need_read_data:
- unget_format (dtp, f);
-}
-
-
-static void
-formatted_transfer_scalar_write (st_parameter_dt *dtp, bt type, void *p, int kind,
- size_t size)
-{
- int pos, bytes_used;
- const fnode *f;
- format_token t;
- int n;
- int consume_data_flag;
-
- /* Change a complex data item into a pair of reals. */
-
- n = (p == NULL) ? 0 : ((type != BT_COMPLEX) ? 1 : 2);
- if (type == BT_COMPLEX)
- {
- type = BT_REAL;
- size /= 2;
- }
-
- /* If there's an EOR condition, we simulate finalizing the transfer
- by doing nothing. */
- if (dtp->u.p.eor_condition)
- return;
-
- /* Set this flag so that commas in reads cause the read to complete before
- the entire field has been read. The next read field will start right after
- the comma in the stream. (Set to 0 for character reads). */
- dtp->u.p.sf_read_comma =
- dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
-
- for (;;)
- {
- /* If reversion has occurred and there is another real data item,
- then we have to move to the next record. */
- if (dtp->u.p.reversion_flag && n > 0)
- {
- dtp->u.p.reversion_flag = 0;
- next_record (dtp, 0);
- }
-
- consume_data_flag = 1;
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- break;
-
- f = next_format (dtp);
- if (f == NULL)
- {
- /* No data descriptors left. */
- if (unlikely (n > 0))
- generate_error (&dtp->common, LIBERROR_FORMAT,
- "Insufficient data descriptors in format after reversion");
- return;
- }
-
- /* Now discharge T, TR and X movements to the right. This is delayed
- until a data producing format to suppress trailing spaces. */
-
- t = f->format;
- if (dtp->u.p.mode == WRITING && dtp->u.p.skips != 0
- && ((n>0 && ( t == FMT_I || t == FMT_B || t == FMT_O
- || t == FMT_Z || t == FMT_F || t == FMT_E
- || t == FMT_EN || t == FMT_ES || t == FMT_G
- || t == FMT_L || t == FMT_A || t == FMT_D))
- || t == FMT_STRING))
- {
- if (dtp->u.p.skips > 0)
- {
- int tmp;
- write_x (dtp, dtp->u.p.skips, dtp->u.p.pending_spaces);
- tmp = (int)(dtp->u.p.current_unit->recl
- - dtp->u.p.current_unit->bytes_left);
- dtp->u.p.max_pos =
- dtp->u.p.max_pos > tmp ? dtp->u.p.max_pos : tmp;
- }
- if (dtp->u.p.skips < 0)
- {
- if (is_internal_unit (dtp))
- sseek (dtp->u.p.current_unit->s, dtp->u.p.skips, SEEK_CUR);
- else
- fbuf_seek (dtp->u.p.current_unit, dtp->u.p.skips, SEEK_CUR);
- dtp->u.p.current_unit->bytes_left -= (gfc_offset) dtp->u.p.skips;
- }
- dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
- }
-
- bytes_used = (int)(dtp->u.p.current_unit->recl
- - dtp->u.p.current_unit->bytes_left);
-
- if (is_stream_io(dtp))
- bytes_used = 0;
-
- switch (t)
- {
- case FMT_I:
- if (n == 0)
- goto need_data;
- if (require_type (dtp, BT_INTEGER, type, f))
- return;
- write_i (dtp, f, p, kind);
- break;
-
- case FMT_B:
- if (n == 0)
- goto need_data;
- if (!(compile_options.allow_std & GFC_STD_GNU)
- && require_numeric_type (dtp, type, f))
- return;
- if (!(compile_options.allow_std & GFC_STD_F2008)
- && require_type (dtp, BT_INTEGER, type, f))
- return;
- write_b (dtp, f, p, kind);
- break;
-
- case FMT_O:
- if (n == 0)
- goto need_data;
- if (!(compile_options.allow_std & GFC_STD_GNU)
- && require_numeric_type (dtp, type, f))
- return;
- if (!(compile_options.allow_std & GFC_STD_F2008)
- && require_type (dtp, BT_INTEGER, type, f))
- return;
- write_o (dtp, f, p, kind);
- break;
-
- case FMT_Z:
- if (n == 0)
- goto need_data;
- if (!(compile_options.allow_std & GFC_STD_GNU)
- && require_numeric_type (dtp, type, f))
- return;
- if (!(compile_options.allow_std & GFC_STD_F2008)
- && require_type (dtp, BT_INTEGER, type, f))
- return;
- write_z (dtp, f, p, kind);
- break;
-
- case FMT_A:
- if (n == 0)
- goto need_data;
-
- /* It is possible to have FMT_A with something not BT_CHARACTER such
- as when writing out hollerith strings, so check both type
- and kind before calling wide character routines. */
- if (type == BT_CHARACTER && kind == 4)
- write_a_char4 (dtp, f, p, size);
- else
- write_a (dtp, f, p, size);
- break;
-
- case FMT_L:
- if (n == 0)
- goto need_data;
- write_l (dtp, f, p, kind);
- break;
-
- case FMT_D:
- if (n == 0)
- goto need_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- write_d (dtp, f, p, kind);
- break;
-
- case FMT_E:
- if (n == 0)
- goto need_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- write_e (dtp, f, p, kind);
- break;
-
- case FMT_EN:
- if (n == 0)
- goto need_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- write_en (dtp, f, p, kind);
- break;
-
- case FMT_ES:
- if (n == 0)
- goto need_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- write_es (dtp, f, p, kind);
- break;
-
- case FMT_F:
- if (n == 0)
- goto need_data;
- if (require_type (dtp, BT_REAL, type, f))
- return;
- write_f (dtp, f, p, kind);
- break;
-
- case FMT_G:
- if (n == 0)
- goto need_data;
- switch (type)
- {
- case BT_INTEGER:
- write_i (dtp, f, p, kind);
- break;
- case BT_LOGICAL:
- write_l (dtp, f, p, kind);
- break;
- case BT_CHARACTER:
- if (kind == 4)
- write_a_char4 (dtp, f, p, size);
- else
- write_a (dtp, f, p, size);
- break;
- case BT_REAL:
- if (f->u.real.w == 0)
- write_real_g0 (dtp, p, kind, f->u.real.d);
- else
- write_d (dtp, f, p, kind);
- break;
- default:
- internal_error (&dtp->common,
- "formatted_transfer(): Bad type");
- }
- break;
-
- case FMT_STRING:
- consume_data_flag = 0;
- write_constant_string (dtp, f);
- break;
-
- /* Format codes that don't transfer data. */
- case FMT_X:
- case FMT_TR:
- consume_data_flag = 0;
-
- dtp->u.p.skips += f->u.n;
- pos = bytes_used + dtp->u.p.skips - 1;
- dtp->u.p.pending_spaces = pos - dtp->u.p.max_pos + 1;
- /* Writes occur just before the switch on f->format, above, so
- that trailing blanks are suppressed, unless we are doing a
- non-advancing write in which case we want to output the blanks
- now. */
- if (dtp->u.p.advance_status == ADVANCE_NO)
- {
- write_x (dtp, dtp->u.p.skips, dtp->u.p.pending_spaces);
- dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
- }
- break;
-
- case FMT_TL:
- case FMT_T:
- consume_data_flag = 0;
-
- if (f->format == FMT_TL)
- {
-
- /* Handle the special case when no bytes have been used yet.
- Cannot go below zero. */
- if (bytes_used == 0)
- {
- dtp->u.p.pending_spaces -= f->u.n;
- dtp->u.p.skips -= f->u.n;
- dtp->u.p.skips = dtp->u.p.skips < 0 ? 0 : dtp->u.p.skips;
- }
-
- pos = bytes_used - f->u.n;
- }
- else /* FMT_T */
- pos = f->u.n - dtp->u.p.pending_spaces - 1;
-
- /* Standard 10.6.1.1: excessive left tabbing is reset to the
- left tab limit. We do not check if the position has gone
- beyond the end of record because a subsequent tab could
- bring us back again. */
- pos = pos < 0 ? 0 : pos;
-
- dtp->u.p.skips = dtp->u.p.skips + pos - bytes_used;
- dtp->u.p.pending_spaces = dtp->u.p.pending_spaces
- + pos - dtp->u.p.max_pos;
- dtp->u.p.pending_spaces = dtp->u.p.pending_spaces < 0
- ? 0 : dtp->u.p.pending_spaces;
- break;
-
- case FMT_S:
- consume_data_flag = 0;
- dtp->u.p.sign_status = SIGN_S;
- break;
-
- case FMT_SS:
- consume_data_flag = 0;
- dtp->u.p.sign_status = SIGN_SS;
- break;
-
- case FMT_SP:
- consume_data_flag = 0;
- dtp->u.p.sign_status = SIGN_SP;
- break;
-
- case FMT_BN:
- consume_data_flag = 0 ;
- dtp->u.p.blank_status = BLANK_NULL;
- break;
-
- case FMT_BZ:
- consume_data_flag = 0;
- dtp->u.p.blank_status = BLANK_ZERO;
- break;
-
- case FMT_DC:
- consume_data_flag = 0;
- dtp->u.p.current_unit->decimal_status = DECIMAL_COMMA;
- break;
-
- case FMT_DP:
- consume_data_flag = 0;
- dtp->u.p.current_unit->decimal_status = DECIMAL_POINT;
- break;
-
- case FMT_RC:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_COMPATIBLE;
- break;
-
- case FMT_RD:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_DOWN;
- break;
-
- case FMT_RN:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_NEAREST;
- break;
-
- case FMT_RP:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_PROCDEFINED;
- break;
-
- case FMT_RU:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_UP;
- break;
-
- case FMT_RZ:
- consume_data_flag = 0;
- dtp->u.p.current_unit->round_status = ROUND_ZERO;
- break;
-
- case FMT_P:
- consume_data_flag = 0;
- dtp->u.p.scale_factor = f->u.k;
- break;
-
- case FMT_DOLLAR:
- consume_data_flag = 0;
- dtp->u.p.seen_dollar = 1;
- break;
-
- case FMT_SLASH:
- consume_data_flag = 0;
- dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
- next_record (dtp, 0);
- break;
-
- case FMT_COLON:
- /* A colon descriptor causes us to exit this loop (in
- particular preventing another / descriptor from being
- processed) unless there is another data item to be
- transferred. */
- consume_data_flag = 0;
- if (n == 0)
- return;
- break;
-
- default:
- internal_error (&dtp->common, "Bad format node");
- }
-
- /* Adjust the item count and data pointer. */
-
- if ((consume_data_flag > 0) && (n > 0))
- {
- n--;
- p = ((char *) p) + size;
- }
-
- pos = (int)(dtp->u.p.current_unit->recl - dtp->u.p.current_unit->bytes_left);
- dtp->u.p.max_pos = (dtp->u.p.max_pos > pos) ? dtp->u.p.max_pos : pos;
- }
-
- return;
-
- /* Come here when we need a data descriptor but don't have one. We
- push the current format node back onto the input, then return and
- let the user program call us back with the data. */
- need_data:
- unget_format (dtp, f);
-}
-
- /* This function is first called from data_init_transfer to initiate the loop
- over each item in the format, transferring data as required. Subsequent
- calls to this function occur for each data item foound in the READ/WRITE
- statement. The item_count is incremented for each call. Since the first
- call is from data_transfer_init, the item_count is always one greater than
- the actual count number of the item being transferred. */
-
-static void
-formatted_transfer (st_parameter_dt *dtp, bt type, void *p, int kind,
- size_t size, size_t nelems)
-{
- size_t elem;
- char *tmp;
-
- tmp = (char *) p;
- size_t stride = type == BT_CHARACTER ?
- size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
- if (dtp->u.p.mode == READING)
- {
- /* Big loop over all the elements. */
- for (elem = 0; elem < nelems; elem++)
- {
- dtp->u.p.item_count++;
- formatted_transfer_scalar_read (dtp, type, tmp + stride*elem, kind, size);
- }
- }
- else
- {
- /* Big loop over all the elements. */
- for (elem = 0; elem < nelems; elem++)
- {
- dtp->u.p.item_count++;
- formatted_transfer_scalar_write (dtp, type, tmp + stride*elem, kind, size);
- }
- }
-}
-
-
-/* Data transfer entry points. The type of the data entity is
- implicit in the subroutine call. This prevents us from having to
- share a common enum with the compiler. */
-
-void
-transfer_integer (st_parameter_dt *dtp, void *p, int kind)
-{
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- return;
- dtp->u.p.transfer (dtp, BT_INTEGER, p, kind, kind, 1);
-}
-
-void
-transfer_integer_write (st_parameter_dt *dtp, void *p, int kind)
-{
- transfer_integer (dtp, p, kind);
-}
-
-void
-transfer_real (st_parameter_dt *dtp, void *p, int kind)
-{
- size_t size;
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- return;
- size = size_from_real_kind (kind);
- dtp->u.p.transfer (dtp, BT_REAL, p, kind, size, 1);
-}
-
-void
-transfer_real_write (st_parameter_dt *dtp, void *p, int kind)
-{
- transfer_real (dtp, p, kind);
-}
-
-void
-transfer_logical (st_parameter_dt *dtp, void *p, int kind)
-{
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- return;
- dtp->u.p.transfer (dtp, BT_LOGICAL, p, kind, kind, 1);
-}
-
-void
-transfer_logical_write (st_parameter_dt *dtp, void *p, int kind)
-{
- transfer_logical (dtp, p, kind);
-}
-
-void
-transfer_character (st_parameter_dt *dtp, void *p, int len)
-{
- static char *empty_string[0];
-
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- return;
-
- /* Strings of zero length can have p == NULL, which confuses the
- transfer routines into thinking we need more data elements. To avoid
- this, we give them a nice pointer. */
- if (len == 0 && p == NULL)
- p = empty_string;
-
- /* Set kind here to 1. */
- dtp->u.p.transfer (dtp, BT_CHARACTER, p, 1, len, 1);
-}
-
-void
-transfer_character_write (st_parameter_dt *dtp, void *p, int len)
-{
- transfer_character (dtp, p, len);
-}
-
-void
-transfer_character_wide (st_parameter_dt *dtp, void *p, int len, int kind)
-{
- static char *empty_string[0];
-
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- return;
-
- /* Strings of zero length can have p == NULL, which confuses the
- transfer routines into thinking we need more data elements. To avoid
- this, we give them a nice pointer. */
- if (len == 0 && p == NULL)
- p = empty_string;
-
- /* Here we pass the actual kind value. */
- dtp->u.p.transfer (dtp, BT_CHARACTER, p, kind, len, 1);
-}
-
-void
-transfer_character_wide_write (st_parameter_dt *dtp, void *p, int len, int kind)
-{
- transfer_character_wide (dtp, p, len, kind);
-}
-
-void
-transfer_complex (st_parameter_dt *dtp, void *p, int kind)
-{
- size_t size;
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- return;
- size = size_from_complex_kind (kind);
- dtp->u.p.transfer (dtp, BT_COMPLEX, p, kind, size, 1);
-}
-
-void
-transfer_complex_write (st_parameter_dt *dtp, void *p, int kind)
-{
- transfer_complex (dtp, p, kind);
-}
-
-void
-transfer_array (st_parameter_dt *dtp, gfc_array_char *desc, int kind,
- gfc_charlen_type charlen)
-{
- index_type count[GFC_MAX_DIMENSIONS];
- index_type extent[GFC_MAX_DIMENSIONS];
- index_type stride[GFC_MAX_DIMENSIONS];
- index_type stride0, rank, size, n;
- size_t tsize;
- char *data;
- bt iotype;
-
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- return;
-
- iotype = (bt) GFC_DESCRIPTOR_TYPE (desc);
- size = iotype == BT_CHARACTER ? charlen : GFC_DESCRIPTOR_SIZE (desc);
-
- rank = GFC_DESCRIPTOR_RANK (desc);
- for (n = 0; n < rank; n++)
- {
- count[n] = 0;
- stride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(desc,n);
- extent[n] = GFC_DESCRIPTOR_EXTENT(desc,n);
-
- /* If the extent of even one dimension is zero, then the entire
- array section contains zero elements, so we return after writing
- a zero array record. */
- if (extent[n] <= 0)
- {
- data = NULL;
- tsize = 0;
- dtp->u.p.transfer (dtp, iotype, data, kind, size, tsize);
- return;
- }
- }
-
- stride0 = stride[0];
-
- /* If the innermost dimension has a stride of 1, we can do the transfer
- in contiguous chunks. */
- if (stride0 == size)
- tsize = extent[0];
- else
- tsize = 1;
-
- data = GFC_DESCRIPTOR_DATA (desc);
-
- while (data)
- {
- dtp->u.p.transfer (dtp, iotype, data, kind, size, tsize);
- data += stride0 * tsize;
- count[0] += tsize;
- n = 0;
- while (count[n] == extent[n])
- {
- count[n] = 0;
- data -= stride[n] * extent[n];
- n++;
- if (n == rank)
- {
- data = NULL;
- break;
- }
- else
- {
- count[n]++;
- data += stride[n];
- }
- }
- }
-}
-
-void
-transfer_array_write (st_parameter_dt *dtp, gfc_array_char *desc, int kind,
- gfc_charlen_type charlen)
-{
- transfer_array (dtp, desc, kind, charlen);
-}
-
-/* Preposition a sequential unformatted file while reading. */
-
-static void
-us_read (st_parameter_dt *dtp, int continued)
-{
- ssize_t n, nr;
- GFC_INTEGER_4 i4;
- GFC_INTEGER_8 i8;
- gfc_offset i;
-
- if (compile_options.record_marker == 0)
- n = sizeof (GFC_INTEGER_4);
- else
- n = compile_options.record_marker;
-
- nr = sread (dtp->u.p.current_unit->s, &i, n);
- if (unlikely (nr < 0))
- {
- generate_error (&dtp->common, LIBERROR_BAD_US, NULL);
- return;
- }
- else if (nr == 0)
- {
- hit_eof (dtp);
- return; /* end of file */
- }
- else if (unlikely (n != nr))
- {
- generate_error (&dtp->common, LIBERROR_BAD_US, NULL);
- return;
- }
-
- /* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */
- if (likely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE))
- {
- switch (nr)
- {
- case sizeof(GFC_INTEGER_4):
- memcpy (&i4, &i, sizeof (i4));
- i = i4;
- break;
-
- case sizeof(GFC_INTEGER_8):
- memcpy (&i8, &i, sizeof (i8));
- i = i8;
- break;
-
- default:
- runtime_error ("Illegal value for record marker");
- break;
- }
- }
- else
- {
- uint32_t u32;
- uint64_t u64;
- switch (nr)
- {
- case sizeof(GFC_INTEGER_4):
- memcpy (&u32, &i, sizeof (u32));
- u32 = __builtin_bswap32 (u32);
- memcpy (&i4, &u32, sizeof (i4));
- i = i4;
- break;
-
- case sizeof(GFC_INTEGER_8):
- memcpy (&u64, &i, sizeof (u64));
- u64 = __builtin_bswap64 (u64);
- memcpy (&i8, &u64, sizeof (i8));
- i = i8;
- break;
-
- default:
- runtime_error ("Illegal value for record marker");
- break;
- }
- }
-
- if (i >= 0)
- {
- dtp->u.p.current_unit->bytes_left_subrecord = i;
- dtp->u.p.current_unit->continued = 0;
- }
- else
- {
- dtp->u.p.current_unit->bytes_left_subrecord = -i;
- dtp->u.p.current_unit->continued = 1;
- }
-
- if (! continued)
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
-}
-
-
-/* Preposition a sequential unformatted file while writing. This
- amount to writing a bogus length that will be filled in later. */
-
-static void
-us_write (st_parameter_dt *dtp, int continued)
-{
- ssize_t nbytes;
- gfc_offset dummy;
-
- dummy = 0;
-
- if (compile_options.record_marker == 0)
- nbytes = sizeof (GFC_INTEGER_4);
- else
- nbytes = compile_options.record_marker ;
-
- if (swrite (dtp->u.p.current_unit->s, &dummy, nbytes) != nbytes)
- generate_error (&dtp->common, LIBERROR_OS, NULL);
-
- /* For sequential unformatted, if RECL= was not specified in the OPEN
- we write until we have more bytes than can fit in the subrecord
- markers, then we write a new subrecord. */
-
- dtp->u.p.current_unit->bytes_left_subrecord =
- dtp->u.p.current_unit->recl_subrecord;
- dtp->u.p.current_unit->continued = continued;
-}
-
-
-/* Position to the next record prior to transfer. We are assumed to
- be before the next record. We also calculate the bytes in the next
- record. */
-
-static void
-pre_position (st_parameter_dt *dtp)
-{
- if (dtp->u.p.current_unit->current_record)
- return; /* Already positioned. */
-
- switch (current_mode (dtp))
- {
- case FORMATTED_STREAM:
- case UNFORMATTED_STREAM:
- /* There are no records with stream I/O. If the position was specified
- data_transfer_init has already positioned the file. If no position
- was specified, we continue from where we last left off. I.e.
- there is nothing to do here. */
- break;
-
- case UNFORMATTED_SEQUENTIAL:
- if (dtp->u.p.mode == READING)
- us_read (dtp, 0);
- else
- us_write (dtp, 0);
-
- break;
-
- case FORMATTED_SEQUENTIAL:
- case FORMATTED_DIRECT:
- case UNFORMATTED_DIRECT:
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
- break;
- }
-
- dtp->u.p.current_unit->current_record = 1;
-}
-
-
-/* Initialize things for a data transfer. This code is common for
- both reading and writing. */
-
-static void
-data_transfer_init (st_parameter_dt *dtp, int read_flag)
-{
- unit_flags u_flags; /* Used for creating a unit if needed. */
- GFC_INTEGER_4 cf = dtp->common.flags;
- namelist_info *ionml;
-
- ionml = ((cf & IOPARM_DT_IONML_SET) != 0) ? dtp->u.p.ionml : NULL;
-
- memset (&dtp->u.p, 0, sizeof (dtp->u.p));
-
- dtp->u.p.ionml = ionml;
- dtp->u.p.mode = read_flag ? READING : WRITING;
-
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- return;
-
- if ((cf & IOPARM_DT_HAS_SIZE) != 0)
- dtp->u.p.size_used = 0; /* Initialize the count. */
-
- dtp->u.p.current_unit = get_unit (dtp, 1);
- if (dtp->u.p.current_unit->s == NULL)
- { /* Open the unit with some default flags. */
- st_parameter_open opp;
- unit_convert conv;
-
- if (dtp->common.unit < 0)
- {
- close_unit (dtp->u.p.current_unit);
- dtp->u.p.current_unit = NULL;
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "Bad unit number in statement");
- return;
- }
- memset (&u_flags, '\0', sizeof (u_flags));
- u_flags.access = ACCESS_SEQUENTIAL;
- u_flags.action = ACTION_READWRITE;
-
- /* Is it unformatted? */
- if (!(cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT
- | IOPARM_DT_IONML_SET)))
- u_flags.form = FORM_UNFORMATTED;
- else
- u_flags.form = FORM_UNSPECIFIED;
-
- u_flags.delim = DELIM_UNSPECIFIED;
- u_flags.blank = BLANK_UNSPECIFIED;
- u_flags.pad = PAD_UNSPECIFIED;
- u_flags.decimal = DECIMAL_UNSPECIFIED;
- u_flags.encoding = ENCODING_UNSPECIFIED;
- u_flags.async = ASYNC_UNSPECIFIED;
- u_flags.round = ROUND_UNSPECIFIED;
- u_flags.sign = SIGN_UNSPECIFIED;
-
- u_flags.status = STATUS_UNKNOWN;
-
- conv = get_unformatted_convert (dtp->common.unit);
-
- if (conv == GFC_CONVERT_NONE)
- conv = compile_options.convert;
-
- /* We use big_endian, which is 0 on little-endian machines
- and 1 on big-endian machines. */
- switch (conv)
- {
- case GFC_CONVERT_NATIVE:
- case GFC_CONVERT_SWAP:
- break;
-
- case GFC_CONVERT_BIG:
- conv = big_endian ? GFC_CONVERT_NATIVE : GFC_CONVERT_SWAP;
- break;
-
- case GFC_CONVERT_LITTLE:
- conv = big_endian ? GFC_CONVERT_SWAP : GFC_CONVERT_NATIVE;
- break;
-
- default:
- internal_error (&opp.common, "Illegal value for CONVERT");
- break;
- }
-
- u_flags.convert = conv;
-
- opp.common = dtp->common;
- opp.common.flags &= IOPARM_COMMON_MASK;
- dtp->u.p.current_unit = new_unit (&opp, dtp->u.p.current_unit, &u_flags);
- dtp->common.flags &= ~IOPARM_COMMON_MASK;
- dtp->common.flags |= (opp.common.flags & IOPARM_COMMON_MASK);
- if (dtp->u.p.current_unit == NULL)
- return;
- }
-
- /* Check the action. */
-
- if (read_flag && dtp->u.p.current_unit->flags.action == ACTION_WRITE)
- {
- generate_error (&dtp->common, LIBERROR_BAD_ACTION,
- "Cannot read from file opened for WRITE");
- return;
- }
-
- if (!read_flag && dtp->u.p.current_unit->flags.action == ACTION_READ)
- {
- generate_error (&dtp->common, LIBERROR_BAD_ACTION,
- "Cannot write to file opened for READ");
- return;
- }
-
- dtp->u.p.first_item = 1;
-
- /* Check the format. */
-
- if ((cf & IOPARM_DT_HAS_FORMAT) != 0)
- parse_format (dtp);
-
- if (dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED
- && (cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT))
- != 0)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "Format present for UNFORMATTED data transfer");
- return;
- }
-
- if ((cf & IOPARM_DT_HAS_NAMELIST_NAME) != 0 && dtp->u.p.ionml != NULL)
- {
- if ((cf & IOPARM_DT_HAS_FORMAT) != 0)
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "A format cannot be specified with a namelist");
- }
- else if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED &&
- !(cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT)))
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "Missing format for FORMATTED data transfer");
- }
-
- if (is_internal_unit (dtp)
- && dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "Internal file cannot be accessed by UNFORMATTED "
- "data transfer");
- return;
- }
-
- /* Check the record or position number. */
-
- if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT
- && (cf & IOPARM_DT_HAS_REC) == 0)
- {
- generate_error (&dtp->common, LIBERROR_MISSING_OPTION,
- "Direct access data transfer requires record number");
- return;
- }
-
- if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
- {
- if ((cf & IOPARM_DT_HAS_REC) != 0)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "Record number not allowed for sequential access "
- "data transfer");
- return;
- }
-
- if (dtp->u.p.current_unit->endfile == AFTER_ENDFILE)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "Sequential READ or WRITE not allowed after "
- "EOF marker, possibly use REWIND or BACKSPACE");
- return;
- }
-
- }
- /* Process the ADVANCE option. */
-
- dtp->u.p.advance_status
- = !(cf & IOPARM_DT_HAS_ADVANCE) ? ADVANCE_UNSPECIFIED :
- find_option (&dtp->common, dtp->advance, dtp->advance_len, advance_opt,
- "Bad ADVANCE parameter in data transfer statement");
-
- if (dtp->u.p.advance_status != ADVANCE_UNSPECIFIED)
- {
- if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "ADVANCE specification conflicts with sequential "
- "access");
- return;
- }
-
- if (is_internal_unit (dtp))
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "ADVANCE specification conflicts with internal file");
- return;
- }
-
- if ((cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT))
- != IOPARM_DT_HAS_FORMAT)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "ADVANCE specification requires an explicit format");
- return;
- }
- }
-
- if (read_flag)
- {
- dtp->u.p.current_unit->previous_nonadvancing_write = 0;
-
- if ((cf & IOPARM_EOR) != 0 && dtp->u.p.advance_status != ADVANCE_NO)
- {
- generate_error (&dtp->common, LIBERROR_MISSING_OPTION,
- "EOR specification requires an ADVANCE specification "
- "of NO");
- return;
- }
-
- if ((cf & IOPARM_DT_HAS_SIZE) != 0
- && dtp->u.p.advance_status != ADVANCE_NO)
- {
- generate_error (&dtp->common, LIBERROR_MISSING_OPTION,
- "SIZE specification requires an ADVANCE "
- "specification of NO");
- return;
- }
- }
- else
- { /* Write constraints. */
- if ((cf & IOPARM_END) != 0)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "END specification cannot appear in a write "
- "statement");
- return;
- }
-
- if ((cf & IOPARM_EOR) != 0)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "EOR specification cannot appear in a write "
- "statement");
- return;
- }
-
- if ((cf & IOPARM_DT_HAS_SIZE) != 0)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "SIZE specification cannot appear in a write "
- "statement");
- return;
- }
- }
-
- if (dtp->u.p.advance_status == ADVANCE_UNSPECIFIED)
- dtp->u.p.advance_status = ADVANCE_YES;
-
- /* Check the decimal mode. */
- dtp->u.p.current_unit->decimal_status
- = !(cf & IOPARM_DT_HAS_DECIMAL) ? DECIMAL_UNSPECIFIED :
- find_option (&dtp->common, dtp->decimal, dtp->decimal_len,
- decimal_opt, "Bad DECIMAL parameter in data transfer "
- "statement");
-
- if (dtp->u.p.current_unit->decimal_status == DECIMAL_UNSPECIFIED)
- dtp->u.p.current_unit->decimal_status = dtp->u.p.current_unit->flags.decimal;
-
- /* Check the round mode. */
- dtp->u.p.current_unit->round_status
- = !(cf & IOPARM_DT_HAS_ROUND) ? ROUND_UNSPECIFIED :
- find_option (&dtp->common, dtp->round, dtp->round_len,
- round_opt, "Bad ROUND parameter in data transfer "
- "statement");
-
- if (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED)
- dtp->u.p.current_unit->round_status = dtp->u.p.current_unit->flags.round;
-
- /* Check the sign mode. */
- dtp->u.p.sign_status
- = !(cf & IOPARM_DT_HAS_SIGN) ? SIGN_UNSPECIFIED :
- find_option (&dtp->common, dtp->sign, dtp->sign_len, sign_opt,
- "Bad SIGN parameter in data transfer statement");
-
- if (dtp->u.p.sign_status == SIGN_UNSPECIFIED)
- dtp->u.p.sign_status = dtp->u.p.current_unit->flags.sign;
-
- /* Check the blank mode. */
- dtp->u.p.blank_status
- = !(cf & IOPARM_DT_HAS_BLANK) ? BLANK_UNSPECIFIED :
- find_option (&dtp->common, dtp->blank, dtp->blank_len,
- blank_opt,
- "Bad BLANK parameter in data transfer statement");
-
- if (dtp->u.p.blank_status == BLANK_UNSPECIFIED)
- dtp->u.p.blank_status = dtp->u.p.current_unit->flags.blank;
-
- /* Check the delim mode. */
- dtp->u.p.current_unit->delim_status
- = !(cf & IOPARM_DT_HAS_DELIM) ? DELIM_UNSPECIFIED :
- find_option (&dtp->common, dtp->delim, dtp->delim_len,
- delim_opt, "Bad DELIM parameter in data transfer statement");
-
- if (dtp->u.p.current_unit->delim_status == DELIM_UNSPECIFIED)
- dtp->u.p.current_unit->delim_status = dtp->u.p.current_unit->flags.delim;
-
- /* Check the pad mode. */
- dtp->u.p.current_unit->pad_status
- = !(cf & IOPARM_DT_HAS_PAD) ? PAD_UNSPECIFIED :
- find_option (&dtp->common, dtp->pad, dtp->pad_len, pad_opt,
- "Bad PAD parameter in data transfer statement");
-
- if (dtp->u.p.current_unit->pad_status == PAD_UNSPECIFIED)
- dtp->u.p.current_unit->pad_status = dtp->u.p.current_unit->flags.pad;
-
- /* Check to see if we might be reading what we wrote before */
-
- if (dtp->u.p.mode != dtp->u.p.current_unit->mode
- && !is_internal_unit (dtp))
- {
- int pos = fbuf_reset (dtp->u.p.current_unit);
- if (pos != 0)
- sseek (dtp->u.p.current_unit->s, pos, SEEK_CUR);
- sflush(dtp->u.p.current_unit->s);
- }
-
- /* Check the POS= specifier: that it is in range and that it is used with a
- unit that has been connected for STREAM access. F2003 9.5.1.10. */
-
- if (((cf & IOPARM_DT_HAS_POS) != 0))
- {
- if (is_stream_io (dtp))
- {
-
- if (dtp->pos <= 0)
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "POS=specifier must be positive");
- return;
- }
-
- if (dtp->pos >= dtp->u.p.current_unit->maxrec)
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "POS=specifier too large");
- return;
- }
-
- dtp->rec = dtp->pos;
-
- if (dtp->u.p.mode == READING)
- {
- /* Reset the endfile flag; if we hit EOF during reading
- we'll set the flag and generate an error at that point
- rather than worrying about it here. */
- dtp->u.p.current_unit->endfile = NO_ENDFILE;
- }
-
- if (dtp->pos != dtp->u.p.current_unit->strm_pos)
- {
- fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
- if (sseek (dtp->u.p.current_unit->s, dtp->pos - 1, SEEK_SET) < 0)
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
- dtp->u.p.current_unit->strm_pos = dtp->pos;
- }
- }
- else
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "POS=specifier not allowed, "
- "Try OPEN with ACCESS='stream'");
- return;
- }
- }
-
-
- /* Sanity checks on the record number. */
- if ((cf & IOPARM_DT_HAS_REC) != 0)
- {
- if (dtp->rec <= 0)
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "Record number must be positive");
- return;
- }
-
- if (dtp->rec >= dtp->u.p.current_unit->maxrec)
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "Record number too large");
- return;
- }
-
- /* Make sure format buffer is reset. */
- if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED)
- fbuf_reset (dtp->u.p.current_unit);
-
-
- /* Check whether the record exists to be read. Only
- a partial record needs to exist. */
-
- if (dtp->u.p.mode == READING && (dtp->rec - 1)
- * dtp->u.p.current_unit->recl >= ssize (dtp->u.p.current_unit->s))
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "Non-existing record number");
- return;
- }
-
- /* Position the file. */
- if (sseek (dtp->u.p.current_unit->s, (gfc_offset) (dtp->rec - 1)
- * dtp->u.p.current_unit->recl, SEEK_SET) < 0)
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
-
- /* TODO: This is required to maintain compatibility between
- 4.3 and 4.4 runtime. Remove when ABI changes from 4.3 */
-
- if (is_stream_io (dtp))
- dtp->u.p.current_unit->strm_pos = dtp->rec;
-
- /* TODO: Un-comment this code when ABI changes from 4.3.
- if (dtp->u.p.current_unit->flags.access == ACCESS_STREAM)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "Record number not allowed for stream access "
- "data transfer");
- return;
- } */
- }
-
- /* Bugware for badly written mixed C-Fortran I/O. */
- if (!is_internal_unit (dtp))
- flush_if_preconnected(dtp->u.p.current_unit->s);
-
- dtp->u.p.current_unit->mode = dtp->u.p.mode;
-
- /* Set the maximum position reached from the previous I/O operation. This
- could be greater than zero from a previous non-advancing write. */
- dtp->u.p.max_pos = dtp->u.p.current_unit->saved_pos;
-
- pre_position (dtp);
-
-
- /* Set up the subroutine that will handle the transfers. */
-
- if (read_flag)
- {
- if (dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED)
- dtp->u.p.transfer = unformatted_read;
- else
- {
- if ((cf & IOPARM_DT_LIST_FORMAT) != 0)
- {
- dtp->u.p.last_char = EOF - 1;
- dtp->u.p.transfer = list_formatted_read;
- }
- else
- dtp->u.p.transfer = formatted_transfer;
- }
- }
- else
- {
- if (dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED)
- dtp->u.p.transfer = unformatted_write;
- else
- {
- if ((cf & IOPARM_DT_LIST_FORMAT) != 0)
- dtp->u.p.transfer = list_formatted_write;
- else
- dtp->u.p.transfer = formatted_transfer;
- }
- }
-
- /* Make sure that we don't do a read after a nonadvancing write. */
-
- if (read_flag)
- {
- if (dtp->u.p.current_unit->read_bad && !is_stream_io (dtp))
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "Cannot READ after a nonadvancing WRITE");
- return;
- }
- }
- else
- {
- if (dtp->u.p.advance_status == ADVANCE_YES && !dtp->u.p.seen_dollar)
- dtp->u.p.current_unit->read_bad = 1;
- }
-
- /* Start the data transfer if we are doing a formatted transfer. */
- if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED
- && ((cf & (IOPARM_DT_LIST_FORMAT | IOPARM_DT_HAS_NAMELIST_NAME)) == 0)
- && dtp->u.p.ionml == NULL)
- formatted_transfer (dtp, 0, NULL, 0, 0, 1);
-}
-
-/* Initialize an array_loop_spec given the array descriptor. The function
- returns the index of the last element of the array, and also returns
- starting record, where the first I/O goes to (necessary in case of
- negative strides). */
-
-gfc_offset
-init_loop_spec (gfc_array_char *desc, array_loop_spec *ls,
- gfc_offset *start_record)
-{
- int rank = GFC_DESCRIPTOR_RANK(desc);
- int i;
- gfc_offset index;
- int empty;
-
- empty = 0;
- index = 1;
- *start_record = 0;
-
- for (i=0; i<rank; i++)
- {
- ls[i].idx = GFC_DESCRIPTOR_LBOUND(desc,i);
- ls[i].start = GFC_DESCRIPTOR_LBOUND(desc,i);
- ls[i].end = GFC_DESCRIPTOR_UBOUND(desc,i);
- ls[i].step = GFC_DESCRIPTOR_STRIDE(desc,i);
- empty = empty || (GFC_DESCRIPTOR_UBOUND(desc,i)
- < GFC_DESCRIPTOR_LBOUND(desc,i));
-
- if (GFC_DESCRIPTOR_STRIDE(desc,i) > 0)
- {
- index += (GFC_DESCRIPTOR_EXTENT(desc,i) - 1)
- * GFC_DESCRIPTOR_STRIDE(desc,i);
- }
- else
- {
- index -= (GFC_DESCRIPTOR_EXTENT(desc,i) - 1)
- * GFC_DESCRIPTOR_STRIDE(desc,i);
- *start_record -= (GFC_DESCRIPTOR_EXTENT(desc,i) - 1)
- * GFC_DESCRIPTOR_STRIDE(desc,i);
- }
- }
-
- if (empty)
- return 0;
- else
- return index;
-}
-
-/* Determine the index to the next record in an internal unit array by
- by incrementing through the array_loop_spec. */
-
-gfc_offset
-next_array_record (st_parameter_dt *dtp, array_loop_spec *ls, int *finished)
-{
- int i, carry;
- gfc_offset index;
-
- carry = 1;
- index = 0;
-
- for (i = 0; i < dtp->u.p.current_unit->rank; i++)
- {
- if (carry)
- {
- ls[i].idx++;
- if (ls[i].idx > ls[i].end)
- {
- ls[i].idx = ls[i].start;
- carry = 1;
- }
- else
- carry = 0;
- }
- index = index + (ls[i].idx - ls[i].start) * ls[i].step;
- }
-
- *finished = carry;
-
- return index;
-}
-
-
-
-/* Skip to the end of the current record, taking care of an optional
- record marker of size bytes. If the file is not seekable, we
- read chunks of size MAX_READ until we get to the right
- position. */
-
-static void
-skip_record (st_parameter_dt *dtp, ssize_t bytes)
-{
- ssize_t rlength, readb;
- static const ssize_t MAX_READ = 4096;
- char p[MAX_READ];
-
- dtp->u.p.current_unit->bytes_left_subrecord += bytes;
- if (dtp->u.p.current_unit->bytes_left_subrecord == 0)
- return;
-
- /* Direct access files do not generate END conditions,
- only I/O errors. */
- if (sseek (dtp->u.p.current_unit->s,
- dtp->u.p.current_unit->bytes_left_subrecord, SEEK_CUR) < 0)
- {
- /* Seeking failed, fall back to seeking by reading data. */
- while (dtp->u.p.current_unit->bytes_left_subrecord > 0)
- {
- rlength =
- (MAX_READ < dtp->u.p.current_unit->bytes_left_subrecord) ?
- MAX_READ : dtp->u.p.current_unit->bytes_left_subrecord;
-
- readb = sread (dtp->u.p.current_unit->s, p, rlength);
- if (readb < 0)
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
-
- dtp->u.p.current_unit->bytes_left_subrecord -= readb;
- }
- return;
- }
- dtp->u.p.current_unit->bytes_left_subrecord = 0;
-}
-
-
-/* Advance to the next record reading unformatted files, taking
- care of subrecords. If complete_record is nonzero, we loop
- until all subrecords are cleared. */
-
-static void
-next_record_r_unf (st_parameter_dt *dtp, int complete_record)
-{
- size_t bytes;
-
- bytes = compile_options.record_marker == 0 ?
- sizeof (GFC_INTEGER_4) : compile_options.record_marker;
-
- while(1)
- {
-
- /* Skip over tail */
-
- skip_record (dtp, bytes);
-
- if ( ! (complete_record && dtp->u.p.current_unit->continued))
- return;
-
- us_read (dtp, 1);
- }
-}
-
-
-static gfc_offset
-min_off (gfc_offset a, gfc_offset b)
-{
- return (a < b ? a : b);
-}
-
-
-/* Space to the next record for read mode. */
-
-static void
-next_record_r (st_parameter_dt *dtp, int done)
-{
- gfc_offset record;
- int bytes_left;
- char p;
- int cc;
-
- switch (current_mode (dtp))
- {
- /* No records in unformatted STREAM I/O. */
- case UNFORMATTED_STREAM:
- return;
-
- case UNFORMATTED_SEQUENTIAL:
- next_record_r_unf (dtp, 1);
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
- break;
-
- case FORMATTED_DIRECT:
- case UNFORMATTED_DIRECT:
- skip_record (dtp, dtp->u.p.current_unit->bytes_left);
- break;
-
- case FORMATTED_STREAM:
- case FORMATTED_SEQUENTIAL:
- /* read_sf has already terminated input because of an '\n', or
- we have hit EOF. */
- if (dtp->u.p.sf_seen_eor)
- {
- dtp->u.p.sf_seen_eor = 0;
- break;
- }
-
- if (is_internal_unit (dtp))
- {
- if (is_array_io (dtp))
- {
- int finished;
-
- record = next_array_record (dtp, dtp->u.p.current_unit->ls,
- &finished);
- if (!done && finished)
- hit_eof (dtp);
-
- /* Now seek to this record. */
- record = record * dtp->u.p.current_unit->recl;
- if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
- {
- generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
- break;
- }
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
- }
- else
- {
- bytes_left = (int) dtp->u.p.current_unit->bytes_left;
- bytes_left = min_off (bytes_left,
- ssize (dtp->u.p.current_unit->s)
- - stell (dtp->u.p.current_unit->s));
- if (sseek (dtp->u.p.current_unit->s,
- bytes_left, SEEK_CUR) < 0)
- {
- generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
- break;
- }
- dtp->u.p.current_unit->bytes_left
- = dtp->u.p.current_unit->recl;
- }
- break;
- }
- else
- {
- do
- {
- errno = 0;
- cc = fbuf_getc (dtp->u.p.current_unit);
- if (cc == EOF)
- {
- if (errno != 0)
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- else
- {
- if (is_stream_io (dtp)
- || dtp->u.p.current_unit->pad_status == PAD_NO
- || dtp->u.p.current_unit->bytes_left
- == dtp->u.p.current_unit->recl)
- hit_eof (dtp);
- }
- break;
- }
-
- if (is_stream_io (dtp))
- dtp->u.p.current_unit->strm_pos++;
-
- p = (char) cc;
- }
- while (p != '\n');
- }
- break;
- }
-}
-
-
-/* Small utility function to write a record marker, taking care of
- byte swapping and of choosing the correct size. */
-
-static int
-write_us_marker (st_parameter_dt *dtp, const gfc_offset buf)
-{
- size_t len;
- GFC_INTEGER_4 buf4;
- GFC_INTEGER_8 buf8;
-
- if (compile_options.record_marker == 0)
- len = sizeof (GFC_INTEGER_4);
- else
- len = compile_options.record_marker;
-
- /* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */
- if (likely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE))
- {
- switch (len)
- {
- case sizeof (GFC_INTEGER_4):
- buf4 = buf;
- return swrite (dtp->u.p.current_unit->s, &buf4, len);
- break;
-
- case sizeof (GFC_INTEGER_8):
- buf8 = buf;
- return swrite (dtp->u.p.current_unit->s, &buf8, len);
- break;
-
- default:
- runtime_error ("Illegal value for record marker");
- break;
- }
- }
- else
- {
- uint32_t u32;
- uint64_t u64;
- switch (len)
- {
- case sizeof (GFC_INTEGER_4):
- buf4 = buf;
- memcpy (&u32, &buf4, sizeof (u32));
- u32 = __builtin_bswap32 (u32);
- return swrite (dtp->u.p.current_unit->s, &u32, len);
- break;
-
- case sizeof (GFC_INTEGER_8):
- buf8 = buf;
- memcpy (&u64, &buf8, sizeof (u64));
- u64 = __builtin_bswap64 (u64);
- return swrite (dtp->u.p.current_unit->s, &u64, len);
- break;
-
- default:
- runtime_error ("Illegal value for record marker");
- break;
- }
- }
-
-}
-
-/* Position to the next (sub)record in write mode for
- unformatted sequential files. */
-
-static void
-next_record_w_unf (st_parameter_dt *dtp, int next_subrecord)
-{
- gfc_offset m, m_write, record_marker;
-
- /* Bytes written. */
- m = dtp->u.p.current_unit->recl_subrecord
- - dtp->u.p.current_unit->bytes_left_subrecord;
-
- /* Write the length tail. If we finish a record containing
- subrecords, we write out the negative length. */
-
- if (dtp->u.p.current_unit->continued)
- m_write = -m;
- else
- m_write = m;
-
- if (unlikely (write_us_marker (dtp, m_write) < 0))
- goto io_error;
-
- if (compile_options.record_marker == 0)
- record_marker = sizeof (GFC_INTEGER_4);
- else
- record_marker = compile_options.record_marker;
-
- /* Seek to the head and overwrite the bogus length with the real
- length. */
-
- if (unlikely (sseek (dtp->u.p.current_unit->s, - m - 2 * record_marker,
- SEEK_CUR) < 0))
- goto io_error;
-
- if (next_subrecord)
- m_write = -m;
- else
- m_write = m;
-
- if (unlikely (write_us_marker (dtp, m_write) < 0))
- goto io_error;
-
- /* Seek past the end of the current record. */
-
- if (unlikely (sseek (dtp->u.p.current_unit->s, m + record_marker,
- SEEK_CUR) < 0))
- goto io_error;
-
- return;
-
- io_error:
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
-
-}
-
-
-/* Utility function like memset() but operating on streams. Return
- value is same as for POSIX write(). */
-
-static ssize_t
-sset (stream * s, int c, ssize_t nbyte)
-{
- static const int WRITE_CHUNK = 256;
- char p[WRITE_CHUNK];
- ssize_t bytes_left, trans;
-
- if (nbyte < WRITE_CHUNK)
- memset (p, c, nbyte);
- else
- memset (p, c, WRITE_CHUNK);
-
- bytes_left = nbyte;
- while (bytes_left > 0)
- {
- trans = (bytes_left < WRITE_CHUNK) ? bytes_left : WRITE_CHUNK;
- trans = swrite (s, p, trans);
- if (trans <= 0)
- return trans;
- bytes_left -= trans;
- }
-
- return nbyte - bytes_left;
-}
-
-
-/* Position to the next record in write mode. */
-
-static void
-next_record_w (st_parameter_dt *dtp, int done)
-{
- gfc_offset m, record, max_pos;
- int length;
-
- /* Zero counters for X- and T-editing. */
- max_pos = dtp->u.p.max_pos;
- dtp->u.p.max_pos = dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
-
- switch (current_mode (dtp))
- {
- /* No records in unformatted STREAM I/O. */
- case UNFORMATTED_STREAM:
- return;
-
- case FORMATTED_DIRECT:
- if (dtp->u.p.current_unit->bytes_left == 0)
- break;
-
- fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
- fbuf_flush (dtp->u.p.current_unit, WRITING);
- if (sset (dtp->u.p.current_unit->s, ' ',
- dtp->u.p.current_unit->bytes_left)
- != dtp->u.p.current_unit->bytes_left)
- goto io_error;
-
- break;
-
- case UNFORMATTED_DIRECT:
- if (dtp->u.p.current_unit->bytes_left > 0)
- {
- length = (int) dtp->u.p.current_unit->bytes_left;
- if (sset (dtp->u.p.current_unit->s, 0, length) != length)
- goto io_error;
- }
- break;
-
- case UNFORMATTED_SEQUENTIAL:
- next_record_w_unf (dtp, 0);
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
- break;
-
- case FORMATTED_STREAM:
- case FORMATTED_SEQUENTIAL:
-
- if (is_internal_unit (dtp))
- {
- char *p;
- if (is_array_io (dtp))
- {
- int finished;
-
- length = (int) dtp->u.p.current_unit->bytes_left;
-
- /* If the farthest position reached is greater than current
- position, adjust the position and set length to pad out
- whats left. Otherwise just pad whats left.
- (for character array unit) */
- m = dtp->u.p.current_unit->recl
- - dtp->u.p.current_unit->bytes_left;
- if (max_pos > m)
- {
- length = (int) (max_pos - m);
- if (sseek (dtp->u.p.current_unit->s,
- length, SEEK_CUR) < 0)
- {
- generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
- return;
- }
- length = (int) (dtp->u.p.current_unit->recl - max_pos);
- }
-
- p = write_block (dtp, length);
- if (p == NULL)
- return;
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, ' ', length);
- }
- else
- memset (p, ' ', length);
-
- /* Now that the current record has been padded out,
- determine where the next record in the array is. */
- record = next_array_record (dtp, dtp->u.p.current_unit->ls,
- &finished);
- if (finished)
- dtp->u.p.current_unit->endfile = AT_ENDFILE;
-
- /* Now seek to this record */
- record = record * dtp->u.p.current_unit->recl;
-
- if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
- {
- generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
- return;
- }
-
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
- }
- else
- {
- length = 1;
-
- /* If this is the last call to next_record move to the farthest
- position reached and set length to pad out the remainder
- of the record. (for character scaler unit) */
- if (done)
- {
- m = dtp->u.p.current_unit->recl
- - dtp->u.p.current_unit->bytes_left;
- if (max_pos > m)
- {
- length = (int) (max_pos - m);
- if (sseek (dtp->u.p.current_unit->s,
- length, SEEK_CUR) < 0)
- {
- generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
- return;
- }
- length = (int) (dtp->u.p.current_unit->recl - max_pos);
- }
- else
- length = (int) dtp->u.p.current_unit->bytes_left;
- }
- if (length > 0)
- {
- p = write_block (dtp, length);
- if (p == NULL)
- return;
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, (gfc_char4_t) ' ', length);
- }
- else
- memset (p, ' ', length);
- }
- }
- }
- else
- {
-#ifdef HAVE_CRLF
- const int len = 2;
-#else
- const int len = 1;
-#endif
- fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
- char * p = fbuf_alloc (dtp->u.p.current_unit, len);
- if (!p)
- goto io_error;
-#ifdef HAVE_CRLF
- *(p++) = '\r';
-#endif
- *p = '\n';
- if (is_stream_io (dtp))
- {
- dtp->u.p.current_unit->strm_pos += len;
- if (dtp->u.p.current_unit->strm_pos
- < ssize (dtp->u.p.current_unit->s))
- unit_truncate (dtp->u.p.current_unit,
- dtp->u.p.current_unit->strm_pos - 1,
- &dtp->common);
- }
- }
-
- break;
-
- io_error:
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- break;
- }
-}
-
-/* Position to the next record, which means moving to the end of the
- current record. This can happen under several different
- conditions. If the done flag is not set, we get ready to process
- the next record. */
-
-void
-next_record (st_parameter_dt *dtp, int done)
-{
- gfc_offset fp; /* File position. */
-
- dtp->u.p.current_unit->read_bad = 0;
-
- if (dtp->u.p.mode == READING)
- next_record_r (dtp, done);
- else
- next_record_w (dtp, done);
-
- if (!is_stream_io (dtp))
- {
- /* Since we have changed the position, set it to unspecified so
- that INQUIRE(POSITION=) knows it needs to look into it. */
- if (done)
- dtp->u.p.current_unit->flags.position = POSITION_UNSPECIFIED;
-
- dtp->u.p.current_unit->current_record = 0;
- if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
- {
- fp = stell (dtp->u.p.current_unit->s);
- /* Calculate next record, rounding up partial records. */
- dtp->u.p.current_unit->last_record =
- (fp + dtp->u.p.current_unit->recl - 1) /
- dtp->u.p.current_unit->recl;
- }
- else
- dtp->u.p.current_unit->last_record++;
- }
-
- if (!done)
- pre_position (dtp);
-
- fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
-}
-
-
-/* Finalize the current data transfer. For a nonadvancing transfer,
- this means advancing to the next record. For internal units close the
- stream associated with the unit. */
-
-static void
-finalize_transfer (st_parameter_dt *dtp)
-{
- GFC_INTEGER_4 cf = dtp->common.flags;
-
- if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
- *dtp->size = dtp->u.p.size_used;
-
- if (dtp->u.p.eor_condition)
- {
- generate_error (&dtp->common, LIBERROR_EOR, NULL);
- return;
- }
-
- if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
- {
- if (dtp->u.p.current_unit && current_mode (dtp) == UNFORMATTED_SEQUENTIAL)
- dtp->u.p.current_unit->current_record = 0;
- return;
- }
-
- if ((dtp->u.p.ionml != NULL)
- && (cf & IOPARM_DT_HAS_NAMELIST_NAME) != 0)
- {
- if ((cf & IOPARM_DT_NAMELIST_READ_MODE) != 0)
- namelist_read (dtp);
- else
- namelist_write (dtp);
- }
-
- dtp->u.p.transfer = NULL;
- if (dtp->u.p.current_unit == NULL)
- return;
-
- if ((cf & IOPARM_DT_LIST_FORMAT) != 0 && dtp->u.p.mode == READING)
- {
- finish_list_read (dtp);
- return;
- }
-
- if (dtp->u.p.mode == WRITING)
- dtp->u.p.current_unit->previous_nonadvancing_write
- = dtp->u.p.advance_status == ADVANCE_NO;
-
- if (is_stream_io (dtp))
- {
- if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED
- && dtp->u.p.advance_status != ADVANCE_NO)
- next_record (dtp, 1);
-
- return;
- }
-
- dtp->u.p.current_unit->current_record = 0;
-
- if (!is_internal_unit (dtp) && dtp->u.p.seen_dollar)
- {
- fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
- dtp->u.p.seen_dollar = 0;
- return;
- }
-
- /* For non-advancing I/O, save the current maximum position for use in the
- next I/O operation if needed. */
- if (dtp->u.p.advance_status == ADVANCE_NO)
- {
- int bytes_written = (int) (dtp->u.p.current_unit->recl
- - dtp->u.p.current_unit->bytes_left);
- dtp->u.p.current_unit->saved_pos =
- dtp->u.p.max_pos > 0 ? dtp->u.p.max_pos - bytes_written : 0;
- fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
- return;
- }
- else if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED
- && dtp->u.p.mode == WRITING && !is_internal_unit (dtp))
- fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
-
- dtp->u.p.current_unit->saved_pos = 0;
-
- next_record (dtp, 1);
-}
-
-/* Transfer function for IOLENGTH. It doesn't actually do any
- data transfer, it just updates the length counter. */
-
-static void
-iolength_transfer (st_parameter_dt *dtp, bt type __attribute__((unused)),
- void *dest __attribute__ ((unused)),
- int kind __attribute__((unused)),
- size_t size, size_t nelems)
-{
- if ((dtp->common.flags & IOPARM_DT_HAS_IOLENGTH) != 0)
- *dtp->iolength += (GFC_IO_INT) (size * nelems);
-}
-
-
-/* Initialize the IOLENGTH data transfer. This function is in essence
- a very much simplified version of data_transfer_init(), because it
- doesn't have to deal with units at all. */
-
-static void
-iolength_transfer_init (st_parameter_dt *dtp)
-{
- if ((dtp->common.flags & IOPARM_DT_HAS_IOLENGTH) != 0)
- *dtp->iolength = 0;
-
- memset (&dtp->u.p, 0, sizeof (dtp->u.p));
-
- /* Set up the subroutine that will handle the transfers. */
-
- dtp->u.p.transfer = iolength_transfer;
-}
-
-
-/* Library entry point for the IOLENGTH form of the INQUIRE
- statement. The IOLENGTH form requires no I/O to be performed, but
- it must still be a runtime library call so that we can determine
- the iolength for dynamic arrays and such. */
-
-extern void st_iolength (st_parameter_dt *);
-export_proto(st_iolength);
-
-void
-st_iolength (st_parameter_dt *dtp)
-{
- library_start (&dtp->common);
- iolength_transfer_init (dtp);
-}
-
-extern void st_iolength_done (st_parameter_dt *);
-export_proto(st_iolength_done);
-
-void
-st_iolength_done (st_parameter_dt *dtp __attribute__((unused)))
-{
- free_ionml (dtp);
- library_end ();
-}
-
-
-/* The READ statement. */
-
-extern void st_read (st_parameter_dt *);
-export_proto(st_read);
-
-void
-st_read (st_parameter_dt *dtp)
-{
- library_start (&dtp->common);
-
- data_transfer_init (dtp, 1);
-}
-
-extern void st_read_done (st_parameter_dt *);
-export_proto(st_read_done);
-
-void
-st_read_done (st_parameter_dt *dtp)
-{
- finalize_transfer (dtp);
- if (is_internal_unit (dtp) || dtp->u.p.format_not_saved)
- free_format_data (dtp->u.p.fmt);
- free_ionml (dtp);
- if (dtp->u.p.current_unit != NULL)
- unlock_unit (dtp->u.p.current_unit);
-
- free_internal_unit (dtp);
-
- library_end ();
-}
-
-extern void st_write (st_parameter_dt *);
-export_proto(st_write);
-
-void
-st_write (st_parameter_dt *dtp)
-{
- library_start (&dtp->common);
- data_transfer_init (dtp, 0);
-}
-
-extern void st_write_done (st_parameter_dt *);
-export_proto(st_write_done);
-
-void
-st_write_done (st_parameter_dt *dtp)
-{
- finalize_transfer (dtp);
-
- /* Deal with endfile conditions associated with sequential files. */
-
- if (dtp->u.p.current_unit != NULL
- && dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
- switch (dtp->u.p.current_unit->endfile)
- {
- case AT_ENDFILE: /* Remain at the endfile record. */
- break;
-
- case AFTER_ENDFILE:
- dtp->u.p.current_unit->endfile = AT_ENDFILE; /* Just at it now. */
- break;
-
- case NO_ENDFILE:
- /* Get rid of whatever is after this record. */
- if (!is_internal_unit (dtp))
- unit_truncate (dtp->u.p.current_unit,
- stell (dtp->u.p.current_unit->s),
- &dtp->common);
- dtp->u.p.current_unit->endfile = AT_ENDFILE;
- break;
- }
-
- if (is_internal_unit (dtp) || dtp->u.p.format_not_saved)
- free_format_data (dtp->u.p.fmt);
- free_ionml (dtp);
- if (dtp->u.p.current_unit != NULL)
- unlock_unit (dtp->u.p.current_unit);
-
- free_internal_unit (dtp);
-
- library_end ();
-}
-
-
-/* F2003: This is a stub for the runtime portion of the WAIT statement. */
-void
-st_wait (st_parameter_wait *wtp __attribute__((unused)))
-{
-}
-
-
-/* Receives the scalar information for namelist objects and stores it
- in a linked list of namelist_info types. */
-
-extern void st_set_nml_var (st_parameter_dt *dtp, void *, char *,
- GFC_INTEGER_4, gfc_charlen_type, GFC_INTEGER_4);
-export_proto(st_set_nml_var);
-
-
-void
-st_set_nml_var (st_parameter_dt *dtp, void * var_addr, char * var_name,
- GFC_INTEGER_4 len, gfc_charlen_type string_length,
- GFC_INTEGER_4 dtype)
-{
- namelist_info *t1 = NULL;
- namelist_info *nml;
- size_t var_name_len = strlen (var_name);
-
- nml = (namelist_info*) xmalloc (sizeof (namelist_info));
-
- nml->mem_pos = var_addr;
-
- nml->var_name = (char*) xmalloc (var_name_len + 1);
- memcpy (nml->var_name, var_name, var_name_len);
- nml->var_name[var_name_len] = '\0';
-
- nml->len = (int) len;
- nml->string_length = (index_type) string_length;
-
- nml->var_rank = (int) (dtype & GFC_DTYPE_RANK_MASK);
- nml->size = (index_type) (dtype >> GFC_DTYPE_SIZE_SHIFT);
- nml->type = (bt) ((dtype & GFC_DTYPE_TYPE_MASK) >> GFC_DTYPE_TYPE_SHIFT);
-
- if (nml->var_rank > 0)
- {
- nml->dim = (descriptor_dimension*)
- xmalloc (nml->var_rank * sizeof (descriptor_dimension));
- nml->ls = (array_loop_spec*)
- xmalloc (nml->var_rank * sizeof (array_loop_spec));
- }
- else
- {
- nml->dim = NULL;
- nml->ls = NULL;
- }
-
- nml->next = NULL;
-
- if ((dtp->common.flags & IOPARM_DT_IONML_SET) == 0)
- {
- dtp->common.flags |= IOPARM_DT_IONML_SET;
- dtp->u.p.ionml = nml;
- }
- else
- {
- for (t1 = dtp->u.p.ionml; t1->next; t1 = t1->next);
- t1->next = nml;
- }
-}
-
-/* Store the dimensional information for the namelist object. */
-extern void st_set_nml_var_dim (st_parameter_dt *, GFC_INTEGER_4,
- index_type, index_type,
- index_type);
-export_proto(st_set_nml_var_dim);
-
-void
-st_set_nml_var_dim (st_parameter_dt *dtp, GFC_INTEGER_4 n_dim,
- index_type stride, index_type lbound,
- index_type ubound)
-{
- namelist_info * nml;
- int n;
-
- n = (int)n_dim;
-
- for (nml = dtp->u.p.ionml; nml->next; nml = nml->next);
-
- GFC_DIMENSION_SET(nml->dim[n],lbound,ubound,stride);
-}
-
-
-/* Once upon a time, a poor innocent Fortran program was reading a
- file, when suddenly it hit the end-of-file (EOF). Unfortunately
- the OS doesn't tell whether we're at the EOF or whether we already
- went past it. Luckily our hero, libgfortran, keeps track of this.
- Call this function when you detect an EOF condition. See Section
- 9.10.2 in F2003. */
-
-void
-hit_eof (st_parameter_dt * dtp)
-{
- dtp->u.p.current_unit->flags.position = POSITION_APPEND;
-
- if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
- switch (dtp->u.p.current_unit->endfile)
- {
- case NO_ENDFILE:
- case AT_ENDFILE:
- generate_error (&dtp->common, LIBERROR_END, NULL);
- if (!is_internal_unit (dtp) && !dtp->u.p.namelist_mode)
- {
- dtp->u.p.current_unit->endfile = AFTER_ENDFILE;
- dtp->u.p.current_unit->current_record = 0;
- }
- else
- dtp->u.p.current_unit->endfile = AT_ENDFILE;
- break;
-
- case AFTER_ENDFILE:
- generate_error (&dtp->common, LIBERROR_ENDFILE, NULL);
- dtp->u.p.current_unit->current_record = 0;
- break;
- }
- else
- {
- /* Non-sequential files don't have an ENDFILE record, so we
- can't be at AFTER_ENDFILE. */
- dtp->u.p.current_unit->endfile = AT_ENDFILE;
- generate_error (&dtp->common, LIBERROR_END, NULL);
- dtp->u.p.current_unit->current_record = 0;
- }
-}
diff --git a/gcc-4.8.1/libgfortran/io/transfer128.c b/gcc-4.8.1/libgfortran/io/transfer128.c
deleted file mode 100644
index 962a700b4..000000000
--- a/gcc-4.8.1/libgfortran/io/transfer128.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* Copyright (C) 2010-2013 Free Software Foundation, Inc.
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* Note: This file needs to be a separate translation unit (.o file)
- to make sure that for static linkage, the libquad dependence only
- occurs if needed. */
-
-#include "io.h"
-
-
-#if defined(GFC_REAL_16_IS_FLOAT128)
-
-/* The prototypes for the called procedures in transfer.c. */
-
-extern void transfer_real (st_parameter_dt *, void *, int);
-export_proto(transfer_real);
-
-extern void transfer_real_write (st_parameter_dt *, void *, int);
-export_proto(transfer_real_write);
-
-extern void transfer_complex (st_parameter_dt *, void *, int);
-export_proto(transfer_complex);
-
-extern void transfer_complex_write (st_parameter_dt *, void *, int);
-export_proto(transfer_complex_write);
-
-
-/* The prototypes for the procedures in this file. */
-
-extern void transfer_real128 (st_parameter_dt *, void *, int);
-export_proto(transfer_real128);
-
-extern void transfer_real128_write (st_parameter_dt *, void *, int);
-export_proto(transfer_real128_write);
-
-extern void transfer_complex128 (st_parameter_dt *, void *, int);
-export_proto(transfer_complex128);
-
-extern void transfer_complex128_write (st_parameter_dt *, void *, int);
-export_proto(transfer_complex128_write);
-
-
-/* Make sure that libquadmath is pulled in. The functions strtoflt128
- and quadmath_snprintf are weakly referrenced in convert_real and
- write_float; the pointer assignment with USED attribute make sure
- that there is a non-weakref dependence if the quadmath functions
- are used. That avoids segfault when libquadmath is statically linked. */
-static void __attribute__((used)) *tmp1 = strtoflt128;
-static void __attribute__((used)) *tmp2 = quadmath_snprintf;
-
-void
-transfer_real128 (st_parameter_dt *dtp, void *p, int kind)
-{
- transfer_real (dtp, p, kind);
-}
-
-
-void
-transfer_real128_write (st_parameter_dt *dtp, void *p, int kind)
-{
- transfer_real (dtp, p, kind);
-}
-
-
-void
-transfer_complex128 (st_parameter_dt *dtp, void *p, int kind)
-{
- transfer_complex (dtp, p, kind);
-}
-
-
-void
-transfer_complex128_write (st_parameter_dt *dtp, void *p, int kind)
-{
- transfer_complex_write (dtp, p, kind);
-}
-#endif
diff --git a/gcc-4.8.1/libgfortran/io/unit.c b/gcc-4.8.1/libgfortran/io/unit.c
deleted file mode 100644
index f8c1516e0..000000000
--- a/gcc-4.8.1/libgfortran/io/unit.c
+++ /dev/null
@@ -1,838 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "io.h"
-#include "fbuf.h"
-#include "format.h"
-#include "unix.h"
-#include <stdlib.h>
-#include <string.h>
-
-
-/* IO locking rules:
- UNIT_LOCK is a master lock, protecting UNIT_ROOT tree and UNIT_CACHE.
- Concurrent use of different units should be supported, so
- each unit has its own lock, LOCK.
- Open should be atomic with its reopening of units and list_read.c
- in several places needs find_unit another unit while holding stdin
- unit's lock, so it must be possible to acquire UNIT_LOCK while holding
- some unit's lock. Therefore to avoid deadlocks, it is forbidden
- to acquire unit's private locks while holding UNIT_LOCK, except
- for freshly created units (where no other thread can get at their
- address yet) or when using just trylock rather than lock operation.
- In addition to unit's private lock each unit has a WAITERS counter
- and CLOSED flag. WAITERS counter must be either only
- atomically incremented/decremented in all places (if atomic builtins
- are supported), or protected by UNIT_LOCK in all places (otherwise).
- CLOSED flag must be always protected by unit's LOCK.
- After finding a unit in UNIT_CACHE or UNIT_ROOT with UNIT_LOCK held,
- WAITERS must be incremented to avoid concurrent close from freeing
- the unit between unlocking UNIT_LOCK and acquiring unit's LOCK.
- Unit freeing is always done under UNIT_LOCK. If close_unit sees any
- WAITERS, it doesn't free the unit but instead sets the CLOSED flag
- and the thread that decrements WAITERS to zero while CLOSED flag is
- set is responsible for freeing it (while holding UNIT_LOCK).
- flush_all_units operation is iterating over the unit tree with
- increasing UNIT_NUMBER while holding UNIT_LOCK and attempting to
- flush each unit (and therefore needs the unit's LOCK held as well).
- To avoid deadlocks, it just trylocks the LOCK and if unsuccessful,
- remembers the current unit's UNIT_NUMBER, unlocks UNIT_LOCK, acquires
- unit's LOCK and after flushing reacquires UNIT_LOCK and restarts with
- the smallest UNIT_NUMBER above the last one flushed.
-
- If find_unit/find_or_create_unit/find_file/get_unit routines return
- non-NULL, the returned unit has its private lock locked and when the
- caller is done with it, it must call either unlock_unit or close_unit
- on it. unlock_unit or close_unit must be always called only with the
- private lock held. */
-
-/* Subroutines related to units */
-
-/* Unit number to be assigned when NEWUNIT is used in an OPEN statement. */
-#define GFC_FIRST_NEWUNIT -10
-static GFC_INTEGER_4 next_available_newunit = GFC_FIRST_NEWUNIT;
-
-#define CACHE_SIZE 3
-static gfc_unit *unit_cache[CACHE_SIZE];
-gfc_offset max_offset;
-gfc_unit *unit_root;
-#ifdef __GTHREAD_MUTEX_INIT
-__gthread_mutex_t unit_lock = __GTHREAD_MUTEX_INIT;
-#else
-__gthread_mutex_t unit_lock;
-#endif
-
-/* We use these filenames for error reporting. */
-
-static char stdin_name[] = "stdin";
-static char stdout_name[] = "stdout";
-static char stderr_name[] = "stderr";
-
-/* This implementation is based on Stefan Nilsson's article in the
- * July 1997 Doctor Dobb's Journal, "Treaps in Java". */
-
-/* pseudo_random()-- Simple linear congruential pseudorandom number
- * generator. The period of this generator is 44071, which is plenty
- * for our purposes. */
-
-static int
-pseudo_random (void)
-{
- static int x0 = 5341;
-
- x0 = (22611 * x0 + 10) % 44071;
- return x0;
-}
-
-
-/* rotate_left()-- Rotate the treap left */
-
-static gfc_unit *
-rotate_left (gfc_unit * t)
-{
- gfc_unit *temp;
-
- temp = t->right;
- t->right = t->right->left;
- temp->left = t;
-
- return temp;
-}
-
-
-/* rotate_right()-- Rotate the treap right */
-
-static gfc_unit *
-rotate_right (gfc_unit * t)
-{
- gfc_unit *temp;
-
- temp = t->left;
- t->left = t->left->right;
- temp->right = t;
-
- return temp;
-}
-
-
-static int
-compare (int a, int b)
-{
- if (a < b)
- return -1;
- if (a > b)
- return 1;
-
- return 0;
-}
-
-
-/* insert()-- Recursive insertion function. Returns the updated treap. */
-
-static gfc_unit *
-insert (gfc_unit *new, gfc_unit *t)
-{
- int c;
-
- if (t == NULL)
- return new;
-
- c = compare (new->unit_number, t->unit_number);
-
- if (c < 0)
- {
- t->left = insert (new, t->left);
- if (t->priority < t->left->priority)
- t = rotate_right (t);
- }
-
- if (c > 0)
- {
- t->right = insert (new, t->right);
- if (t->priority < t->right->priority)
- t = rotate_left (t);
- }
-
- if (c == 0)
- internal_error (NULL, "insert(): Duplicate key found!");
-
- return t;
-}
-
-
-/* insert_unit()-- Create a new node, insert it into the treap. */
-
-static gfc_unit *
-insert_unit (int n)
-{
- gfc_unit *u = xcalloc (1, sizeof (gfc_unit));
- u->unit_number = n;
-#ifdef __GTHREAD_MUTEX_INIT
- {
- __gthread_mutex_t tmp = __GTHREAD_MUTEX_INIT;
- u->lock = tmp;
- }
-#else
- __GTHREAD_MUTEX_INIT_FUNCTION (&u->lock);
-#endif
- __gthread_mutex_lock (&u->lock);
- u->priority = pseudo_random ();
- unit_root = insert (u, unit_root);
- return u;
-}
-
-
-/* destroy_unit_mutex()-- Destroy the mutex and free memory of unit. */
-
-static void
-destroy_unit_mutex (gfc_unit * u)
-{
- __gthread_mutex_destroy (&u->lock);
- free (u);
-}
-
-
-static gfc_unit *
-delete_root (gfc_unit * t)
-{
- gfc_unit *temp;
-
- if (t->left == NULL)
- return t->right;
- if (t->right == NULL)
- return t->left;
-
- if (t->left->priority > t->right->priority)
- {
- temp = rotate_right (t);
- temp->right = delete_root (t);
- }
- else
- {
- temp = rotate_left (t);
- temp->left = delete_root (t);
- }
-
- return temp;
-}
-
-
-/* delete_treap()-- Delete an element from a tree. The 'old' value
- * does not necessarily have to point to the element to be deleted, it
- * must just point to a treap structure with the key to be deleted.
- * Returns the new root node of the tree. */
-
-static gfc_unit *
-delete_treap (gfc_unit * old, gfc_unit * t)
-{
- int c;
-
- if (t == NULL)
- return NULL;
-
- c = compare (old->unit_number, t->unit_number);
-
- if (c < 0)
- t->left = delete_treap (old, t->left);
- if (c > 0)
- t->right = delete_treap (old, t->right);
- if (c == 0)
- t = delete_root (t);
-
- return t;
-}
-
-
-/* delete_unit()-- Delete a unit from a tree */
-
-static void
-delete_unit (gfc_unit * old)
-{
- unit_root = delete_treap (old, unit_root);
-}
-
-
-/* get_external_unit()-- Given an integer, return a pointer to the unit
- * structure. Returns NULL if the unit does not exist,
- * otherwise returns a locked unit. */
-
-static gfc_unit *
-get_external_unit (int n, int do_create)
-{
- gfc_unit *p;
- int c, created = 0;
-
- __gthread_mutex_lock (&unit_lock);
-retry:
- for (c = 0; c < CACHE_SIZE; c++)
- if (unit_cache[c] != NULL && unit_cache[c]->unit_number == n)
- {
- p = unit_cache[c];
- goto found;
- }
-
- p = unit_root;
- while (p != NULL)
- {
- c = compare (n, p->unit_number);
- if (c < 0)
- p = p->left;
- if (c > 0)
- p = p->right;
- if (c == 0)
- break;
- }
-
- if (p == NULL && do_create)
- {
- p = insert_unit (n);
- created = 1;
- }
-
- if (p != NULL)
- {
- for (c = 0; c < CACHE_SIZE - 1; c++)
- unit_cache[c] = unit_cache[c + 1];
-
- unit_cache[CACHE_SIZE - 1] = p;
- }
-
- if (created)
- {
- /* Newly created units have their lock held already
- from insert_unit. Just unlock UNIT_LOCK and return. */
- __gthread_mutex_unlock (&unit_lock);
- return p;
- }
-
-found:
- if (p != NULL)
- {
- /* Fast path. */
- if (! __gthread_mutex_trylock (&p->lock))
- {
- /* assert (p->closed == 0); */
- __gthread_mutex_unlock (&unit_lock);
- return p;
- }
-
- inc_waiting_locked (p);
- }
-
- __gthread_mutex_unlock (&unit_lock);
-
- if (p != NULL)
- {
- __gthread_mutex_lock (&p->lock);
- if (p->closed)
- {
- __gthread_mutex_lock (&unit_lock);
- __gthread_mutex_unlock (&p->lock);
- if (predec_waiting_locked (p) == 0)
- destroy_unit_mutex (p);
- goto retry;
- }
-
- dec_waiting_unlocked (p);
- }
- return p;
-}
-
-
-gfc_unit *
-find_unit (int n)
-{
- return get_external_unit (n, 0);
-}
-
-
-gfc_unit *
-find_or_create_unit (int n)
-{
- return get_external_unit (n, 1);
-}
-
-
-gfc_unit *
-get_internal_unit (st_parameter_dt *dtp)
-{
- gfc_unit * iunit;
- gfc_offset start_record = 0;
-
- /* Allocate memory for a unit structure. */
-
- iunit = xcalloc (1, sizeof (gfc_unit));
-
-#ifdef __GTHREAD_MUTEX_INIT
- {
- __gthread_mutex_t tmp = __GTHREAD_MUTEX_INIT;
- iunit->lock = tmp;
- }
-#else
- __GTHREAD_MUTEX_INIT_FUNCTION (&iunit->lock);
-#endif
- __gthread_mutex_lock (&iunit->lock);
-
- iunit->recl = dtp->internal_unit_len;
-
- /* For internal units we set the unit number to -1.
- Otherwise internal units can be mistaken for a pre-connected unit or
- some other file I/O unit. */
- iunit->unit_number = -1;
-
- /* Set up the looping specification from the array descriptor, if any. */
-
- if (is_array_io (dtp))
- {
- iunit->rank = GFC_DESCRIPTOR_RANK (dtp->internal_unit_desc);
- iunit->ls = (array_loop_spec *)
- xmalloc (iunit->rank * sizeof (array_loop_spec));
- dtp->internal_unit_len *=
- init_loop_spec (dtp->internal_unit_desc, iunit->ls, &start_record);
-
- start_record *= iunit->recl;
- }
- else
- {
- /* If we are not processing an array, adjust the unit record length not
- to include trailing blanks for list-formatted reads. */
- if (dtp->u.p.mode == READING && !(dtp->common.flags & IOPARM_DT_HAS_FORMAT))
- {
- if (dtp->common.unit == 0)
- {
- dtp->internal_unit_len =
- string_len_trim (dtp->internal_unit_len, dtp->internal_unit);
- iunit->recl = dtp->internal_unit_len;
- }
- else
- {
- dtp->internal_unit_len =
- string_len_trim_char4 (dtp->internal_unit_len,
- (const gfc_char4_t*) dtp->internal_unit);
- iunit->recl = dtp->internal_unit_len;
- }
- }
- }
-
- /* Set initial values for unit parameters. */
- if (dtp->common.unit)
- {
- iunit->s = open_internal4 (dtp->internal_unit - start_record,
- dtp->internal_unit_len, -start_record);
- fbuf_init (iunit, 256);
- }
- else
- iunit->s = open_internal (dtp->internal_unit - start_record,
- dtp->internal_unit_len, -start_record);
-
- iunit->bytes_left = iunit->recl;
- iunit->last_record=0;
- iunit->maxrec=0;
- iunit->current_record=0;
- iunit->read_bad = 0;
- iunit->endfile = NO_ENDFILE;
-
- /* Set flags for the internal unit. */
-
- iunit->flags.access = ACCESS_SEQUENTIAL;
- iunit->flags.action = ACTION_READWRITE;
- iunit->flags.blank = BLANK_NULL;
- iunit->flags.form = FORM_FORMATTED;
- iunit->flags.pad = PAD_YES;
- iunit->flags.status = STATUS_UNSPECIFIED;
- iunit->flags.sign = SIGN_SUPPRESS;
- iunit->flags.decimal = DECIMAL_POINT;
- iunit->flags.encoding = ENCODING_DEFAULT;
- iunit->flags.async = ASYNC_NO;
- iunit->flags.round = ROUND_UNSPECIFIED;
-
- /* Initialize the data transfer parameters. */
-
- dtp->u.p.advance_status = ADVANCE_YES;
- dtp->u.p.seen_dollar = 0;
- dtp->u.p.skips = 0;
- dtp->u.p.pending_spaces = 0;
- dtp->u.p.max_pos = 0;
- dtp->u.p.at_eof = 0;
-
- /* This flag tells us the unit is assigned to internal I/O. */
-
- dtp->u.p.unit_is_internal = 1;
-
- return iunit;
-}
-
-
-/* free_internal_unit()-- Free memory allocated for internal units if any. */
-void
-free_internal_unit (st_parameter_dt *dtp)
-{
- if (!is_internal_unit (dtp))
- return;
-
- if (unlikely (is_char4_unit (dtp)))
- fbuf_destroy (dtp->u.p.current_unit);
-
- if (dtp->u.p.current_unit != NULL)
- {
- free (dtp->u.p.current_unit->ls);
-
- free (dtp->u.p.current_unit->s);
-
- destroy_unit_mutex (dtp->u.p.current_unit);
- }
-}
-
-
-
-/* get_unit()-- Returns the unit structure associated with the integer
- unit or the internal file. */
-
-gfc_unit *
-get_unit (st_parameter_dt *dtp, int do_create)
-{
-
- if ((dtp->common.flags & IOPARM_DT_HAS_INTERNAL_UNIT) != 0)
- return get_internal_unit (dtp);
-
- /* Has to be an external unit. */
-
- dtp->u.p.unit_is_internal = 0;
- dtp->internal_unit_desc = NULL;
-
- return get_external_unit (dtp->common.unit, do_create);
-}
-
-
-/*************************/
-/* Initialize everything. */
-
-void
-init_units (void)
-{
- gfc_unit *u;
- unsigned int i;
-
-#ifndef __GTHREAD_MUTEX_INIT
- __GTHREAD_MUTEX_INIT_FUNCTION (&unit_lock);
-#endif
-
- if (options.stdin_unit >= 0)
- { /* STDIN */
- u = insert_unit (options.stdin_unit);
- u->s = input_stream ();
-
- u->flags.action = ACTION_READ;
-
- u->flags.access = ACCESS_SEQUENTIAL;
- u->flags.form = FORM_FORMATTED;
- u->flags.status = STATUS_OLD;
- u->flags.blank = BLANK_NULL;
- u->flags.pad = PAD_YES;
- u->flags.position = POSITION_ASIS;
- u->flags.sign = SIGN_SUPPRESS;
- u->flags.decimal = DECIMAL_POINT;
- u->flags.encoding = ENCODING_DEFAULT;
- u->flags.async = ASYNC_NO;
- u->flags.round = ROUND_UNSPECIFIED;
-
- u->recl = options.default_recl;
- u->endfile = NO_ENDFILE;
-
- u->file_len = strlen (stdin_name);
- u->file = xmalloc (u->file_len);
- memmove (u->file, stdin_name, u->file_len);
-
- fbuf_init (u, 0);
-
- __gthread_mutex_unlock (&u->lock);
- }
-
- if (options.stdout_unit >= 0)
- { /* STDOUT */
- u = insert_unit (options.stdout_unit);
- u->s = output_stream ();
-
- u->flags.action = ACTION_WRITE;
-
- u->flags.access = ACCESS_SEQUENTIAL;
- u->flags.form = FORM_FORMATTED;
- u->flags.status = STATUS_OLD;
- u->flags.blank = BLANK_NULL;
- u->flags.position = POSITION_ASIS;
- u->flags.sign = SIGN_SUPPRESS;
- u->flags.decimal = DECIMAL_POINT;
- u->flags.encoding = ENCODING_DEFAULT;
- u->flags.async = ASYNC_NO;
- u->flags.round = ROUND_UNSPECIFIED;
-
- u->recl = options.default_recl;
- u->endfile = AT_ENDFILE;
-
- u->file_len = strlen (stdout_name);
- u->file = xmalloc (u->file_len);
- memmove (u->file, stdout_name, u->file_len);
-
- fbuf_init (u, 0);
-
- __gthread_mutex_unlock (&u->lock);
- }
-
- if (options.stderr_unit >= 0)
- { /* STDERR */
- u = insert_unit (options.stderr_unit);
- u->s = error_stream ();
-
- u->flags.action = ACTION_WRITE;
-
- u->flags.access = ACCESS_SEQUENTIAL;
- u->flags.form = FORM_FORMATTED;
- u->flags.status = STATUS_OLD;
- u->flags.blank = BLANK_NULL;
- u->flags.position = POSITION_ASIS;
- u->flags.sign = SIGN_SUPPRESS;
- u->flags.decimal = DECIMAL_POINT;
- u->flags.encoding = ENCODING_DEFAULT;
- u->flags.async = ASYNC_NO;
- u->flags.round = ROUND_UNSPECIFIED;
-
- u->recl = options.default_recl;
- u->endfile = AT_ENDFILE;
-
- u->file_len = strlen (stderr_name);
- u->file = xmalloc (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);
- }
-
- /* Calculate the maximum file offset in a portable manner.
- max will be the largest signed number for the type gfc_offset.
- set a 1 in the LSB and keep a running sum, stopping at MSB-1 bit. */
- max_offset = 0;
- for (i = 0; i < sizeof (max_offset) * 8 - 1; i++)
- max_offset = max_offset + ((gfc_offset) 1 << i);
-}
-
-
-static int
-close_unit_1 (gfc_unit *u, int locked)
-{
- int i, rc;
-
- /* If there are previously written bytes from a write with ADVANCE="no"
- Reposition the buffer before closing. */
- if (u->previous_nonadvancing_write)
- finish_last_advance_record (u);
-
- rc = (u->s == NULL) ? 0 : sclose (u->s) == -1;
-
- u->closed = 1;
- if (!locked)
- __gthread_mutex_lock (&unit_lock);
-
- for (i = 0; i < CACHE_SIZE; i++)
- if (unit_cache[i] == u)
- unit_cache[i] = NULL;
-
- delete_unit (u);
-
- free (u->file);
- u->file = NULL;
- u->file_len = 0;
-
- free_format_hash_table (u);
- fbuf_destroy (u);
-
- if (!locked)
- __gthread_mutex_unlock (&u->lock);
-
- /* If there are any threads waiting in find_unit for this unit,
- avoid freeing the memory, the last such thread will free it
- instead. */
- if (u->waiting == 0)
- destroy_unit_mutex (u);
-
- if (!locked)
- __gthread_mutex_unlock (&unit_lock);
-
- return rc;
-}
-
-void
-unlock_unit (gfc_unit *u)
-{
- __gthread_mutex_unlock (&u->lock);
-}
-
-/* close_unit()-- Close a unit. The stream is closed, and any memory
- associated with the stream is freed. Returns nonzero on I/O error.
- Should be called with the u->lock locked. */
-
-int
-close_unit (gfc_unit *u)
-{
- return close_unit_1 (u, 0);
-}
-
-
-/* close_units()-- Delete units on completion. We just keep deleting
- the root of the treap until there is nothing left.
- Not sure what to do with locking here. Some other thread might be
- holding some unit's lock and perhaps hold it indefinitely
- (e.g. waiting for input from some pipe) and close_units shouldn't
- delay the program too much. */
-
-void
-close_units (void)
-{
- __gthread_mutex_lock (&unit_lock);
- while (unit_root != NULL)
- close_unit_1 (unit_root, 1);
- __gthread_mutex_unlock (&unit_lock);
-}
-
-
-/* High level interface to truncate a file, i.e. flush format buffers,
- and generate an error or set some flags. 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);
- }
-
- /* 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);
- 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. */
-
-char *
-filename_from_unit (int n)
-{
- char *filename;
- gfc_unit *u;
- int c;
-
- /* Find the unit. */
- u = unit_root;
- while (u != NULL)
- {
- c = compare (n, u->unit_number);
- if (c < 0)
- u = u->left;
- if (c > 0)
- u = u->right;
- if (c == 0)
- break;
- }
-
- /* Get the filename. */
- if (u != NULL)
- {
- filename = (char *) xmalloc (u->file_len + 1);
- unpack_filename (filename, u->file, u->file_len);
- return filename;
- }
- else
- return (char *) NULL;
-}
-
-void
-finish_last_advance_record (gfc_unit *u)
-{
-
- if (u->saved_pos > 0)
- fbuf_seek (u, u->saved_pos, SEEK_CUR);
-
- if (!(u->unit_number == options.stdout_unit
- || u->unit_number == options.stderr_unit))
- {
-#ifdef HAVE_CRLF
- const int len = 2;
-#else
- const int len = 1;
-#endif
- 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);
-}
-
-/* Assign a negative number for NEWUNIT in OPEN statements. */
-GFC_INTEGER_4
-get_unique_unit_number (st_parameter_open *opp)
-{
- GFC_INTEGER_4 num;
-
-#ifdef HAVE_SYNC_FETCH_AND_ADD
- num = __sync_fetch_and_add (&next_available_newunit, -1);
-#else
- __gthread_mutex_lock (&unit_lock);
- num = next_available_newunit--;
- __gthread_mutex_unlock (&unit_lock);
-#endif
-
- /* Do not allow NEWUNIT numbers to wrap. */
- if (num > GFC_FIRST_NEWUNIT)
- {
- generate_error (&opp->common, LIBERROR_INTERNAL, "NEWUNIT exhausted");
- return 0;
- }
- return num;
-}
diff --git a/gcc-4.8.1/libgfortran/io/unix.c b/gcc-4.8.1/libgfortran/io/unix.c
deleted file mode 100644
index 8b9d7a773..000000000
--- a/gcc-4.8.1/libgfortran/io/unix.c
+++ /dev/null
@@ -1,1884 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* Unix stream I/O module */
-
-#include "io.h"
-#include "unix.h"
-#include <stdlib.h>
-#include <limits.h>
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include <string.h>
-#include <errno.h>
-
-
-/* For mingw, we don't identify files by their inode number, but by a
- 64-bit identifier created from a BY_HANDLE_FILE_INFORMATION. */
-#ifdef __MINGW32__
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-#if !defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64
-#undef lseek
-#define lseek _lseeki64
-#undef fstat
-#define fstat _fstati64
-#undef stat
-#define stat _stati64
-#endif
-
-#ifndef HAVE_WORKING_STAT
-static uint64_t
-id_from_handle (HANDLE hFile)
-{
- BY_HANDLE_FILE_INFORMATION FileInformation;
-
- if (hFile == INVALID_HANDLE_VALUE)
- return 0;
-
- memset (&FileInformation, 0, sizeof(FileInformation));
- if (!GetFileInformationByHandle (hFile, &FileInformation))
- return 0;
-
- return ((uint64_t) FileInformation.nFileIndexLow)
- | (((uint64_t) FileInformation.nFileIndexHigh) << 32);
-}
-
-
-static uint64_t
-id_from_path (const char *path)
-{
- HANDLE hFile;
- uint64_t res;
-
- if (!path || !*path || access (path, F_OK))
- return (uint64_t) -1;
-
- hFile = CreateFile (path, 0, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
- NULL);
- res = id_from_handle (hFile);
- CloseHandle (hFile);
- return res;
-}
-
-
-static uint64_t
-id_from_fd (const int fd)
-{
- return id_from_handle ((HANDLE) _get_osfhandle (fd));
-}
-
-#endif /* HAVE_WORKING_STAT */
-#endif /* __MINGW32__ */
-
-
-/* min macro that evaluates its arguments only once. */
-#ifdef min
-#undef min
-#endif
-
-#define min(a,b) \
- ({ typeof (a) _a = (a); \
- typeof (b) _b = (b); \
- _a < _b ? _a : _b; })
-
-#ifndef PATH_MAX
-#define PATH_MAX 1024
-#endif
-
-/* These flags aren't defined on all targets (mingw32), so provide them
- here. */
-#ifndef S_IRGRP
-#define S_IRGRP 0
-#endif
-
-#ifndef S_IWGRP
-#define S_IWGRP 0
-#endif
-
-#ifndef S_IROTH
-#define S_IROTH 0
-#endif
-
-#ifndef S_IWOTH
-#define S_IWOTH 0
-#endif
-
-
-#ifndef HAVE_ACCESS
-
-#ifndef W_OK
-#define W_OK 2
-#endif
-
-#ifndef R_OK
-#define R_OK 4
-#endif
-
-#ifndef F_OK
-#define F_OK 0
-#endif
-
-/* Fallback implementation of access() on systems that don't have it.
- Only modes R_OK, W_OK and F_OK are used in this file. */
-
-static int
-fallback_access (const char *path, int mode)
-{
- int fd;
-
- if ((mode & R_OK) && (fd = open (path, O_RDONLY)) < 0)
- return -1;
- close (fd);
-
- if ((mode & W_OK) && (fd = open (path, O_WRONLY)) < 0)
- return -1;
- close (fd);
-
- if (mode == F_OK)
- {
- struct stat st;
- return stat (path, &st);
- }
-
- return 0;
-}
-
-#undef access
-#define access fallback_access
-#endif
-
-
-/* Fallback directory for creating temporary files. P_tmpdir is
- defined on many POSIX platforms. */
-#ifndef P_tmpdir
-#ifdef _P_tmpdir
-#define P_tmpdir _P_tmpdir /* MinGW */
-#else
-#define P_tmpdir "/tmp"
-#endif
-#endif
-
-
-/* Unix and internal stream I/O module */
-
-static const int BUFFER_SIZE = 8192;
-
-typedef struct
-{
- stream st;
-
- gfc_offset buffer_offset; /* File offset of the start of the buffer */
- gfc_offset physical_offset; /* Current physical file offset */
- gfc_offset logical_offset; /* Current logical file offset */
- gfc_offset file_length; /* Length of the file. */
-
- char *buffer; /* Pointer to the buffer. */
- int fd; /* The POSIX file descriptor. */
-
- int active; /* Length of valid bytes in the buffer */
-
- int ndirty; /* Dirty bytes starting at buffer_offset */
-
- /* Cached stat(2) values. */
- dev_t st_dev;
- ino_t st_ino;
-}
-unix_stream;
-
-
-/* fix_fd()-- Given a file descriptor, make sure it is not one of the
- * standard descriptors, returning a non-standard descriptor. If the
- * user specifies that system errors should go to standard output,
- * then closes standard output, we don't want the system errors to a
- * file that has been given file descriptor 1 or 0. We want to send
- * the error to the invalid descriptor. */
-
-static int
-fix_fd (int fd)
-{
-#ifdef HAVE_DUP
- int input, output, error;
-
- input = output = error = 0;
-
- /* Unix allocates the lowest descriptors first, so a loop is not
- required, but this order is. */
- if (fd == STDIN_FILENO)
- {
- fd = dup (fd);
- input = 1;
- }
- if (fd == STDOUT_FILENO)
- {
- fd = dup (fd);
- output = 1;
- }
- if (fd == STDERR_FILENO)
- {
- fd = dup (fd);
- error = 1;
- }
-
- if (input)
- close (STDIN_FILENO);
- if (output)
- close (STDOUT_FILENO);
- if (error)
- close (STDERR_FILENO);
-#endif
-
- return fd;
-}
-
-
-/* If the stream corresponds to a preconnected unit, we flush the
- corresponding C stream. This is bugware for mixed C-Fortran codes
- where the C code doesn't flush I/O before returning. */
-void
-flush_if_preconnected (stream * s)
-{
- int fd;
-
- fd = ((unix_stream *) s)->fd;
- if (fd == STDIN_FILENO)
- fflush (stdin);
- else if (fd == STDOUT_FILENO)
- fflush (stdout);
- else if (fd == STDERR_FILENO)
- fflush (stderr);
-}
-
-
-/********************************************************************
-Raw I/O functions (read, write, seek, tell, truncate, close).
-
-These functions wrap the basic POSIX I/O syscalls. Any deviation in
-semantics is a bug, except the following: write restarts in case
-of being interrupted by a signal, and as the first argument the
-functions take the unix_stream struct rather than an integer file
-descriptor. Also, for POSIX read() and write() a nbyte argument larger
-than SSIZE_MAX is undefined; here the type of nbyte is ssize_t rather
-than size_t as for POSIX read/write.
-*********************************************************************/
-
-static int
-raw_flush (unix_stream * s __attribute__ ((unused)))
-{
- return 0;
-}
-
-static ssize_t
-raw_read (unix_stream * s, void * buf, ssize_t nbyte)
-{
- /* For read we can't do I/O in a loop like raw_write does, because
- that will break applications that wait for interactive I/O. */
- return read (s->fd, buf, nbyte);
-}
-
-static ssize_t
-raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
-{
- ssize_t trans, bytes_left;
- char *buf_st;
-
- bytes_left = nbyte;
- buf_st = (char *) buf;
-
- /* We must write in a loop since some systems don't restart system
- calls in case of a signal. */
- while (bytes_left > 0)
- {
- trans = write (s->fd, buf_st, bytes_left);
- if (trans < 0)
- {
- if (errno == EINTR)
- continue;
- else
- return trans;
- }
- buf_st += trans;
- bytes_left -= trans;
- }
-
- return nbyte - bytes_left;
-}
-
-static gfc_offset
-raw_seek (unix_stream * s, gfc_offset offset, int whence)
-{
- return lseek (s->fd, offset, whence);
-}
-
-static gfc_offset
-raw_tell (unix_stream * s)
-{
- return lseek (s->fd, 0, SEEK_CUR);
-}
-
-static gfc_offset
-raw_size (unix_stream * s)
-{
- struct stat statbuf;
- int ret = fstat (s->fd, &statbuf);
- if (ret == -1)
- return ret;
- if (S_ISREG (statbuf.st_mode))
- return statbuf.st_size;
- else
- return 0;
-}
-
-static int
-raw_truncate (unix_stream * s, gfc_offset length)
-{
-#ifdef __MINGW32__
- HANDLE h;
- gfc_offset cur;
-
- if (isatty (s->fd))
- {
- errno = EBADF;
- return -1;
- }
- h = (HANDLE) _get_osfhandle (s->fd);
- if (h == INVALID_HANDLE_VALUE)
- {
- errno = EBADF;
- return -1;
- }
- cur = lseek (s->fd, 0, SEEK_CUR);
- if (cur == -1)
- return -1;
- if (lseek (s->fd, length, SEEK_SET) == -1)
- goto error;
- if (!SetEndOfFile (h))
- {
- errno = EBADF;
- goto error;
- }
- if (lseek (s->fd, cur, SEEK_SET) == -1)
- return -1;
- return 0;
- error:
- lseek (s->fd, cur, SEEK_SET);
- return -1;
-#elif defined HAVE_FTRUNCATE
- return ftruncate (s->fd, length);
-#elif defined HAVE_CHSIZE
- return chsize (s->fd, length);
-#else
- runtime_error ("required ftruncate or chsize support not present");
- return -1;
-#endif
-}
-
-static int
-raw_close (unix_stream * s)
-{
- int retval;
-
- if (s->fd != STDOUT_FILENO
- && s->fd != STDERR_FILENO
- && s->fd != STDIN_FILENO)
- retval = close (s->fd);
- else
- retval = 0;
- free (s);
- return retval;
-}
-
-static const struct stream_vtable raw_vtable = {
- .read = (void *) raw_read,
- .write = (void *) raw_write,
- .seek = (void *) raw_seek,
- .tell = (void *) raw_tell,
- .size = (void *) raw_size,
- .trunc = (void *) raw_truncate,
- .close = (void *) raw_close,
- .flush = (void *) raw_flush
-};
-
-static int
-raw_init (unix_stream * s)
-{
- s->st.vptr = &raw_vtable;
-
- s->buffer = NULL;
- return 0;
-}
-
-
-/*********************************************************************
-Buffered I/O functions. These functions have the same semantics as the
-raw I/O functions above, except that they are buffered in order to
-improve performance. The buffer must be flushed when switching from
-reading to writing and vice versa. Only supported for regular files.
-*********************************************************************/
-
-static int
-buf_flush (unix_stream * s)
-{
- int writelen;
-
- /* Flushing in read mode means discarding read bytes. */
- s->active = 0;
-
- if (s->ndirty == 0)
- return 0;
-
- if (s->physical_offset != s->buffer_offset
- && lseek (s->fd, s->buffer_offset, SEEK_SET) < 0)
- return -1;
-
- writelen = raw_write (s, s->buffer, s->ndirty);
-
- s->physical_offset = s->buffer_offset + writelen;
-
- if (s->physical_offset > s->file_length)
- s->file_length = s->physical_offset;
-
- s->ndirty -= writelen;
- if (s->ndirty != 0)
- return -1;
-
- return 0;
-}
-
-static ssize_t
-buf_read (unix_stream * s, void * buf, ssize_t nbyte)
-{
- if (s->active == 0)
- s->buffer_offset = s->logical_offset;
-
- /* Is the data we want in the buffer? */
- if (s->logical_offset + nbyte <= s->buffer_offset + s->active
- && s->buffer_offset <= s->logical_offset)
- memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset), nbyte);
- else
- {
- /* First copy the active bytes if applicable, then read the rest
- either directly or filling the buffer. */
- char *p;
- int nread = 0;
- ssize_t to_read, did_read;
- gfc_offset new_logical;
-
- p = (char *) buf;
- if (s->logical_offset >= s->buffer_offset
- && s->buffer_offset + s->active >= s->logical_offset)
- {
- nread = s->active - (s->logical_offset - s->buffer_offset);
- memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset),
- nread);
- p += nread;
- }
- /* At this point we consider all bytes in the buffer discarded. */
- to_read = nbyte - nread;
- new_logical = s->logical_offset + nread;
- if (s->physical_offset != new_logical
- && lseek (s->fd, new_logical, SEEK_SET) < 0)
- return -1;
- s->buffer_offset = s->physical_offset = new_logical;
- if (to_read <= BUFFER_SIZE/2)
- {
- did_read = raw_read (s, s->buffer, BUFFER_SIZE);
- s->physical_offset += did_read;
- s->active = did_read;
- did_read = (did_read > to_read) ? to_read : did_read;
- memcpy (p, s->buffer, did_read);
- }
- else
- {
- did_read = raw_read (s, p, to_read);
- s->physical_offset += did_read;
- s->active = 0;
- }
- nbyte = did_read + nread;
- }
- s->logical_offset += nbyte;
- return nbyte;
-}
-
-static ssize_t
-buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
-{
- if (s->ndirty == 0)
- s->buffer_offset = s->logical_offset;
-
- /* Does the data fit into the buffer? As a special case, if the
- buffer is empty and the request is bigger than BUFFER_SIZE/2,
- write directly. This avoids the case where the buffer would have
- to be flushed at every write. */
- if (!(s->ndirty == 0 && nbyte > BUFFER_SIZE/2)
- && s->logical_offset + nbyte <= s->buffer_offset + BUFFER_SIZE
- && s->buffer_offset <= s->logical_offset
- && s->buffer_offset + s->ndirty >= s->logical_offset)
- {
- memcpy (s->buffer + (s->logical_offset - s->buffer_offset), buf, nbyte);
- int nd = (s->logical_offset - s->buffer_offset) + nbyte;
- if (nd > s->ndirty)
- s->ndirty = nd;
- }
- else
- {
- /* Flush, and either fill the buffer with the new data, or if
- the request is bigger than the buffer size, write directly
- bypassing the buffer. */
- buf_flush (s);
- if (nbyte <= BUFFER_SIZE/2)
- {
- memcpy (s->buffer, buf, nbyte);
- s->buffer_offset = s->logical_offset;
- s->ndirty += nbyte;
- }
- else
- {
- if (s->physical_offset != s->logical_offset)
- {
- if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
- return -1;
- s->physical_offset = s->logical_offset;
- }
-
- nbyte = raw_write (s, buf, nbyte);
- s->physical_offset += nbyte;
- }
- }
- s->logical_offset += nbyte;
- if (s->logical_offset > s->file_length)
- s->file_length = s->logical_offset;
- return nbyte;
-}
-
-static gfc_offset
-buf_seek (unix_stream * s, gfc_offset offset, int whence)
-{
- switch (whence)
- {
- case SEEK_SET:
- break;
- case SEEK_CUR:
- offset += s->logical_offset;
- break;
- case SEEK_END:
- offset += s->file_length;
- break;
- default:
- return -1;
- }
- if (offset < 0)
- {
- errno = EINVAL;
- return -1;
- }
- s->logical_offset = offset;
- return offset;
-}
-
-static gfc_offset
-buf_tell (unix_stream * s)
-{
- return buf_seek (s, 0, SEEK_CUR);
-}
-
-static gfc_offset
-buf_size (unix_stream * s)
-{
- return s->file_length;
-}
-
-static int
-buf_truncate (unix_stream * s, gfc_offset length)
-{
- int r;
-
- if (buf_flush (s) != 0)
- return -1;
- r = raw_truncate (s, length);
- if (r == 0)
- s->file_length = length;
- return r;
-}
-
-static int
-buf_close (unix_stream * s)
-{
- if (buf_flush (s) != 0)
- return -1;
- free (s->buffer);
- return raw_close (s);
-}
-
-static const struct stream_vtable buf_vtable = {
- .read = (void *) buf_read,
- .write = (void *) buf_write,
- .seek = (void *) buf_seek,
- .tell = (void *) buf_tell,
- .size = (void *) buf_size,
- .trunc = (void *) buf_truncate,
- .close = (void *) buf_close,
- .flush = (void *) buf_flush
-};
-
-static int
-buf_init (unix_stream * s)
-{
- s->st.vptr = &buf_vtable;
-
- s->buffer = xmalloc (BUFFER_SIZE);
- return 0;
-}
-
-
-/*********************************************************************
- memory stream functions - These are used for internal files
-
- The idea here is that a single stream structure is created and all
- requests must be satisfied from it. The location and size of the
- buffer is the character variable supplied to the READ or WRITE
- statement.
-
-*********************************************************************/
-
-char *
-mem_alloc_r (stream * strm, int * len)
-{
- unix_stream * s = (unix_stream *) strm;
- gfc_offset n;
- gfc_offset where = s->logical_offset;
-
- if (where < s->buffer_offset || where > s->buffer_offset + s->active)
- return NULL;
-
- n = s->buffer_offset + s->active - where;
- if (*len > n)
- *len = n;
-
- s->logical_offset = where + *len;
-
- return s->buffer + (where - s->buffer_offset);
-}
-
-
-char *
-mem_alloc_r4 (stream * strm, int * len)
-{
- unix_stream * s = (unix_stream *) strm;
- gfc_offset n;
- gfc_offset where = s->logical_offset;
-
- if (where < s->buffer_offset || where > s->buffer_offset + s->active)
- return NULL;
-
- n = s->buffer_offset + s->active - where;
- if (*len > n)
- *len = n;
-
- s->logical_offset = where + *len;
-
- return s->buffer + (where - s->buffer_offset) * 4;
-}
-
-
-char *
-mem_alloc_w (stream * strm, int * len)
-{
- unix_stream * s = (unix_stream *) strm;
- gfc_offset m;
- gfc_offset where = s->logical_offset;
-
- m = where + *len;
-
- if (where < s->buffer_offset)
- return NULL;
-
- if (m > s->file_length)
- return NULL;
-
- s->logical_offset = m;
-
- return s->buffer + (where - s->buffer_offset);
-}
-
-
-gfc_char4_t *
-mem_alloc_w4 (stream * strm, int * len)
-{
- unix_stream * s = (unix_stream *) strm;
- gfc_offset m;
- gfc_offset where = s->logical_offset;
- gfc_char4_t *result = (gfc_char4_t *) s->buffer;
-
- m = where + *len;
-
- if (where < s->buffer_offset)
- return NULL;
-
- if (m > s->file_length)
- return NULL;
-
- s->logical_offset = m;
- return &result[where - s->buffer_offset];
-}
-
-
-/* Stream read function for character(kind=1) internal units. */
-
-static ssize_t
-mem_read (stream * s, void * buf, ssize_t nbytes)
-{
- void *p;
- int nb = nbytes;
-
- p = mem_alloc_r (s, &nb);
- if (p)
- {
- memcpy (buf, p, nb);
- return (ssize_t) nb;
- }
- else
- return 0;
-}
-
-
-/* Stream read function for chracter(kind=4) internal units. */
-
-static ssize_t
-mem_read4 (stream * s, void * buf, ssize_t nbytes)
-{
- void *p;
- int nb = nbytes;
-
- p = mem_alloc_r (s, &nb);
- if (p)
- {
- memcpy (buf, p, nb);
- return (ssize_t) nb;
- }
- else
- return 0;
-}
-
-
-/* Stream write function for character(kind=1) internal units. */
-
-static ssize_t
-mem_write (stream * s, const void * buf, ssize_t nbytes)
-{
- void *p;
- int nb = nbytes;
-
- p = mem_alloc_w (s, &nb);
- if (p)
- {
- memcpy (p, buf, nb);
- return (ssize_t) nb;
- }
- else
- return 0;
-}
-
-
-/* Stream write function for character(kind=4) internal units. */
-
-static ssize_t
-mem_write4 (stream * s, const void * buf, ssize_t nwords)
-{
- gfc_char4_t *p;
- int nw = nwords;
-
- p = mem_alloc_w4 (s, &nw);
- if (p)
- {
- while (nw--)
- *p++ = (gfc_char4_t) *((char *) buf);
- return nwords;
- }
- else
- return 0;
-}
-
-
-static gfc_offset
-mem_seek (stream * strm, gfc_offset offset, int whence)
-{
- unix_stream * s = (unix_stream *) strm;
- switch (whence)
- {
- case SEEK_SET:
- break;
- case SEEK_CUR:
- offset += s->logical_offset;
- break;
- case SEEK_END:
- offset += s->file_length;
- break;
- default:
- return -1;
- }
-
- /* Note that for internal array I/O it's actually possible to have a
- negative offset, so don't check for that. */
- if (offset > s->file_length)
- {
- errno = EINVAL;
- return -1;
- }
-
- s->logical_offset = offset;
-
- /* Returning < 0 is the error indicator for sseek(), so return 0 if
- offset is negative. Thus if the return value is 0, the caller
- has to use stell() to get the real value of logical_offset. */
- if (offset >= 0)
- return offset;
- return 0;
-}
-
-
-static gfc_offset
-mem_tell (stream * s)
-{
- return ((unix_stream *)s)->logical_offset;
-}
-
-
-static int
-mem_truncate (unix_stream * s __attribute__ ((unused)),
- gfc_offset length __attribute__ ((unused)))
-{
- return 0;
-}
-
-
-static int
-mem_flush (unix_stream * s __attribute__ ((unused)))
-{
- return 0;
-}
-
-
-static int
-mem_close (unix_stream * s)
-{
- free (s);
-
- return 0;
-}
-
-static const struct stream_vtable mem_vtable = {
- .read = (void *) mem_read,
- .write = (void *) mem_write,
- .seek = (void *) mem_seek,
- .tell = (void *) mem_tell,
- /* buf_size is not a typo, we just reuse an identical
- implementation. */
- .size = (void *) buf_size,
- .trunc = (void *) mem_truncate,
- .close = (void *) mem_close,
- .flush = (void *) mem_flush
-};
-
-static const struct stream_vtable mem4_vtable = {
- .read = (void *) mem_read4,
- .write = (void *) mem_write4,
- .seek = (void *) mem_seek,
- .tell = (void *) mem_tell,
- /* buf_size is not a typo, we just reuse an identical
- implementation. */
- .size = (void *) buf_size,
- .trunc = (void *) mem_truncate,
- .close = (void *) mem_close,
- .flush = (void *) mem_flush
-};
-
-/*********************************************************************
- Public functions -- A reimplementation of this module needs to
- define functional equivalents of the following.
-*********************************************************************/
-
-/* open_internal()-- Returns a stream structure from a character(kind=1)
- internal file */
-
-stream *
-open_internal (char *base, int length, gfc_offset offset)
-{
- unix_stream *s;
-
- s = xcalloc (1, sizeof (unix_stream));
-
- s->buffer = base;
- s->buffer_offset = offset;
-
- s->active = s->file_length = length;
-
- s->st.vptr = &mem_vtable;
-
- return (stream *) s;
-}
-
-/* open_internal4()-- Returns a stream structure from a character(kind=4)
- internal file */
-
-stream *
-open_internal4 (char *base, int length, gfc_offset offset)
-{
- unix_stream *s;
-
- s = xcalloc (1, sizeof (unix_stream));
-
- s->buffer = base;
- s->buffer_offset = offset;
-
- s->active = s->file_length = length * sizeof (gfc_char4_t);
-
- s->st.vptr = &mem4_vtable;
-
- return (stream *) s;
-}
-
-
-/* fd_to_stream()-- Given an open file descriptor, build a stream
- * around it. */
-
-static stream *
-fd_to_stream (int fd)
-{
- struct stat statbuf;
- unix_stream *s;
-
- s = xcalloc (1, sizeof (unix_stream));
-
- s->fd = fd;
-
- /* Get the current length of the file. */
-
- fstat (fd, &statbuf);
-
- s->st_dev = statbuf.st_dev;
- s->st_ino = statbuf.st_ino;
- s->file_length = statbuf.st_size;
-
- /* Only use buffered IO for regular files. */
- if (S_ISREG (statbuf.st_mode)
- && !options.all_unbuffered
- && !(options.unbuffered_preconnected &&
- (s->fd == STDIN_FILENO
- || s->fd == STDOUT_FILENO
- || s->fd == STDERR_FILENO)))
- buf_init (s);
- else
- raw_init (s);
-
- return (stream *) s;
-}
-
-
-/* Given the Fortran unit number, convert it to a C file descriptor. */
-
-int
-unit_to_fd (int unit)
-{
- gfc_unit *us;
- int fd;
-
- us = find_unit (unit);
- if (us == NULL)
- return -1;
-
- fd = ((unix_stream *) us->s)->fd;
- unlock_unit (us);
- return fd;
-}
-
-
-/* unpack_filename()-- Given a fortran string and a pointer to a
- * buffer that is PATH_MAX characters, convert the fortran string to a
- * C string in the buffer. Returns nonzero if this is not possible. */
-
-int
-unpack_filename (char *cstring, const char *fstring, int len)
-{
- if (fstring == NULL)
- return EFAULT;
- len = fstrlen (fstring, len);
- if (len >= PATH_MAX)
- return ENAMETOOLONG;
-
- memmove (cstring, fstring, len);
- cstring[len] = '\0';
-
- return 0;
-}
-
-
-/* Helper function for tempfile(). Tries to open a temporary file in
- the directory specified by tempdir. If successful, the file name is
- stored in fname and the descriptor returned. Returns -1 on
- failure. */
-
-static int
-tempfile_open (const char *tempdir, char **fname)
-{
- int fd;
- const char *slash = "/";
-#if defined(HAVE_UMASK) && defined(HAVE_MKSTEMP)
- mode_t mode_mask;
-#endif
-
- if (!tempdir)
- return -1;
-
- /* Check for the special case that tempdir ends with a slash or
- backslash. */
- size_t tempdirlen = strlen (tempdir);
- if (*tempdir == 0 || tempdir[tempdirlen - 1] == '/'
-#ifdef __MINGW32__
- || tempdir[tempdirlen - 1] == '\\'
-#endif
- )
- slash = "";
-
- // Take care that the template is longer in the mktemp() branch.
- char * template = xmalloc (tempdirlen + 23);
-
-#ifdef HAVE_MKSTEMP
- snprintf (template, tempdirlen + 23, "%s%sgfortrantmpXXXXXX",
- tempdir, slash);
-
-#ifdef HAVE_UMASK
- /* Temporarily set the umask such that the file has 0600 permissions. */
- mode_mask = umask (S_IXUSR | S_IRWXG | S_IRWXO);
-#endif
-
- fd = mkstemp (template);
-
-#ifdef HAVE_UMASK
- (void) umask (mode_mask);
-#endif
-
-#else /* HAVE_MKSTEMP */
- fd = -1;
- int count = 0;
- size_t slashlen = strlen (slash);
- do
- {
- snprintf (template, tempdirlen + 23, "%s%sgfortrantmpaaaXXXXXX",
- tempdir, slash);
- if (count > 0)
- {
- int c = count;
- template[tempdirlen + slashlen + 13] = 'a' + (c% 26);
- c /= 26;
- template[tempdirlen + slashlen + 12] = 'a' + (c % 26);
- c /= 26;
- template[tempdirlen + slashlen + 11] = 'a' + (c % 26);
- if (c >= 26)
- break;
- }
-
- if (!mktemp (template))
- {
- errno = EEXIST;
- count++;
- continue;
- }
-
-#if defined(HAVE_CRLF) && defined(O_BINARY)
- fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
- S_IRUSR | S_IWUSR);
-#else
- fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-#endif
- }
- while (fd == -1 && errno == EEXIST);
-#endif /* HAVE_MKSTEMP */
-
- *fname = template;
- return fd;
-}
-
-
-/* tempfile()-- Generate a temporary filename for a scratch file and
- * open it. mkstemp() opens the file for reading and writing, but the
- * library mode prevents anything that is not allowed. The descriptor
- * is returned, which is -1 on error. The template is pointed to by
- * opp->file, which is copied into the unit structure
- * and freed later. */
-
-static int
-tempfile (st_parameter_open *opp)
-{
- const char *tempdir;
- char *fname;
- int fd = -1;
-
- tempdir = secure_getenv ("TMPDIR");
- fd = tempfile_open (tempdir, &fname);
-#ifdef __MINGW32__
- if (fd == -1)
- {
- char buffer[MAX_PATH + 1];
- DWORD ret;
- ret = GetTempPath (MAX_PATH, buffer);
- /* If we are not able to get a temp-directory, we use
- current directory. */
- if (ret > MAX_PATH || !ret)
- buffer[0] = 0;
- else
- buffer[ret] = 0;
- tempdir = strdup (buffer);
- fd = tempfile_open (tempdir, &fname);
- }
-#elif defined(__CYGWIN__)
- if (fd == -1)
- {
- tempdir = secure_getenv ("TMP");
- fd = tempfile_open (tempdir, &fname);
- }
- if (fd == -1)
- {
- tempdir = secure_getenv ("TEMP");
- fd = tempfile_open (tempdir, &fname);
- }
-#endif
- if (fd == -1)
- fd = tempfile_open (P_tmpdir, &fname);
-
- opp->file = fname;
- opp->file_len = strlen (fname); /* Don't include trailing nul */
-
- return fd;
-}
-
-
-/* regular_file()-- Open a regular file.
- * Change flags->action if it is ACTION_UNSPECIFIED on entry,
- * unless an error occurs.
- * Returns the descriptor, which is less than zero on error. */
-
-static int
-regular_file (st_parameter_open *opp, unit_flags *flags)
-{
- char path[min(PATH_MAX, opp->file_len + 1)];
- int mode;
- int rwflag;
- int crflag;
- int fd;
- int err;
-
- err = unpack_filename (path, opp->file, opp->file_len);
- if (err)
- {
- errno = err; /* Fake an OS error */
- return -1;
- }
-
-#ifdef __CYGWIN__
- if (opp->file_len == 7)
- {
- if (strncmp (path, "CONOUT$", 7) == 0
- || strncmp (path, "CONERR$", 7) == 0)
- {
- fd = open ("/dev/conout", O_WRONLY);
- flags->action = ACTION_WRITE;
- return fd;
- }
- }
-
- if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
- {
- fd = open ("/dev/conin", O_RDONLY);
- flags->action = ACTION_READ;
- return fd;
- }
-#endif
-
-
-#ifdef __MINGW32__
- if (opp->file_len == 7)
- {
- if (strncmp (path, "CONOUT$", 7) == 0
- || strncmp (path, "CONERR$", 7) == 0)
- {
- fd = open ("CONOUT$", O_WRONLY);
- flags->action = ACTION_WRITE;
- return fd;
- }
- }
-
- if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
- {
- fd = open ("CONIN$", O_RDONLY);
- flags->action = ACTION_READ;
- return fd;
- }
-#endif
-
- rwflag = 0;
-
- switch (flags->action)
- {
- case ACTION_READ:
- rwflag = O_RDONLY;
- break;
-
- case ACTION_WRITE:
- rwflag = O_WRONLY;
- break;
-
- case ACTION_READWRITE:
- case ACTION_UNSPECIFIED:
- rwflag = O_RDWR;
- break;
-
- default:
- internal_error (&opp->common, "regular_file(): Bad action");
- }
-
- switch (flags->status)
- {
- case STATUS_NEW:
- crflag = O_CREAT | O_EXCL;
- break;
-
- case STATUS_OLD: /* open will fail if the file does not exist*/
- crflag = 0;
- break;
-
- case STATUS_UNKNOWN:
- case STATUS_SCRATCH:
- crflag = O_CREAT;
- break;
-
- case STATUS_REPLACE:
- crflag = O_CREAT | O_TRUNC;
- break;
-
- default:
- internal_error (&opp->common, "regular_file(): Bad status");
- }
-
- /* rwflag |= O_LARGEFILE; */
-
-#if defined(HAVE_CRLF) && defined(O_BINARY)
- crflag |= O_BINARY;
-#endif
-
- mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
- fd = open (path, rwflag | crflag, mode);
- if (flags->action != ACTION_UNSPECIFIED)
- return fd;
-
- if (fd >= 0)
- {
- flags->action = ACTION_READWRITE;
- return fd;
- }
- if (errno != EACCES && errno != EROFS)
- return fd;
-
- /* retry for read-only access */
- rwflag = O_RDONLY;
- fd = open (path, rwflag | crflag, mode);
- if (fd >=0)
- {
- flags->action = ACTION_READ;
- return fd; /* success */
- }
-
- if (errno != EACCES)
- return fd; /* failure */
-
- /* retry for write-only access */
- rwflag = O_WRONLY;
- fd = open (path, rwflag | crflag, mode);
- if (fd >=0)
- {
- flags->action = ACTION_WRITE;
- return fd; /* success */
- }
- return fd; /* failure */
-}
-
-
-/* open_external()-- Open an external file, unix specific version.
- * Change flags->action if it is ACTION_UNSPECIFIED on entry.
- * Returns NULL on operating system error. */
-
-stream *
-open_external (st_parameter_open *opp, unit_flags *flags)
-{
- int fd;
-
- if (flags->status == STATUS_SCRATCH)
- {
- fd = tempfile (opp);
- if (flags->action == ACTION_UNSPECIFIED)
- flags->action = ACTION_READWRITE;
-
-#if HAVE_UNLINK_OPEN_FILE
- /* We can unlink scratch files now and it will go away when closed. */
- if (fd >= 0)
- unlink (opp->file);
-#endif
- }
- else
- {
- /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
- * if it succeeds */
- fd = regular_file (opp, flags);
- }
-
- if (fd < 0)
- return NULL;
- fd = fix_fd (fd);
-
- return fd_to_stream (fd);
-}
-
-
-/* input_stream()-- Return a stream pointer to the default input stream.
- * Called on initialization. */
-
-stream *
-input_stream (void)
-{
- return fd_to_stream (STDIN_FILENO);
-}
-
-
-/* output_stream()-- Return a stream pointer to the default output stream.
- * Called on initialization. */
-
-stream *
-output_stream (void)
-{
- stream * s;
-
-#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
- setmode (STDOUT_FILENO, O_BINARY);
-#endif
-
- s = fd_to_stream (STDOUT_FILENO);
- return s;
-}
-
-
-/* error_stream()-- Return a stream pointer to the default error stream.
- * Called on initialization. */
-
-stream *
-error_stream (void)
-{
- stream * s;
-
-#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
- setmode (STDERR_FILENO, O_BINARY);
-#endif
-
- s = fd_to_stream (STDERR_FILENO);
- return s;
-}
-
-
-/* compare_file_filename()-- Given an open stream and a fortran string
- * that is a filename, figure out if the file is the same as the
- * filename. */
-
-int
-compare_file_filename (gfc_unit *u, const char *name, int len)
-{
- char path[min(PATH_MAX, len + 1)];
- struct stat st;
-#ifdef HAVE_WORKING_STAT
- unix_stream *s;
-#else
-# ifdef __MINGW32__
- uint64_t id1, id2;
-# endif
-#endif
-
- if (unpack_filename (path, name, len))
- return 0; /* Can't be the same */
-
- /* If the filename doesn't exist, then there is no match with the
- * existing file. */
-
- if (stat (path, &st) < 0)
- return 0;
-
-#ifdef HAVE_WORKING_STAT
- s = (unix_stream *) (u->s);
- return (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
-#else
-
-# ifdef __MINGW32__
- /* We try to match files by a unique ID. On some filesystems (network
- fs and FAT), we can't generate this unique ID, and will simply compare
- filenames. */
- id1 = id_from_path (path);
- id2 = id_from_fd (((unix_stream *) (u->s))->fd);
- if (id1 || id2)
- return (id1 == id2);
-# endif
-
- if (len != u->file_len)
- return 0;
- return (memcmp(path, u->file, len) == 0);
-#endif
-}
-
-
-#ifdef HAVE_WORKING_STAT
-# define FIND_FILE0_DECL struct stat *st
-# define FIND_FILE0_ARGS st
-#else
-# define FIND_FILE0_DECL uint64_t id, const char *file, gfc_charlen_type file_len
-# define FIND_FILE0_ARGS id, file, file_len
-#endif
-
-/* find_file0()-- Recursive work function for find_file() */
-
-static gfc_unit *
-find_file0 (gfc_unit *u, FIND_FILE0_DECL)
-{
- gfc_unit *v;
-#if defined(__MINGW32__) && !HAVE_WORKING_STAT
- uint64_t id1;
-#endif
-
- if (u == NULL)
- return NULL;
-
-#ifdef HAVE_WORKING_STAT
- if (u->s != NULL)
- {
- unix_stream *s = (unix_stream *) (u->s);
- if (st[0].st_dev == s->st_dev && st[0].st_ino == s->st_ino)
- return u;
- }
-#else
-# ifdef __MINGW32__
- if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
- {
- if (id == id1)
- return u;
- }
- else
-# endif
- if (compare_string (u->file_len, u->file, file_len, file) == 0)
- return u;
-#endif
-
- v = find_file0 (u->left, FIND_FILE0_ARGS);
- if (v != NULL)
- return v;
-
- v = find_file0 (u->right, FIND_FILE0_ARGS);
- if (v != NULL)
- return v;
-
- return NULL;
-}
-
-
-/* find_file()-- Take the current filename and see if there is a unit
- * that has the file already open. Returns a pointer to the unit if so. */
-
-gfc_unit *
-find_file (const char *file, gfc_charlen_type file_len)
-{
- char path[min(PATH_MAX, file_len + 1)];
- struct stat st[1];
- gfc_unit *u;
-#if defined(__MINGW32__) && !HAVE_WORKING_STAT
- uint64_t id = 0ULL;
-#endif
-
- if (unpack_filename (path, file, file_len))
- return NULL;
-
- if (stat (path, &st[0]) < 0)
- return NULL;
-
-#if defined(__MINGW32__) && !HAVE_WORKING_STAT
- id = id_from_path (path);
-#endif
-
- __gthread_mutex_lock (&unit_lock);
-retry:
- u = find_file0 (unit_root, FIND_FILE0_ARGS);
- if (u != NULL)
- {
- /* Fast path. */
- if (! __gthread_mutex_trylock (&u->lock))
- {
- /* assert (u->closed == 0); */
- __gthread_mutex_unlock (&unit_lock);
- return u;
- }
-
- inc_waiting_locked (u);
- }
- __gthread_mutex_unlock (&unit_lock);
- if (u != NULL)
- {
- __gthread_mutex_lock (&u->lock);
- if (u->closed)
- {
- __gthread_mutex_lock (&unit_lock);
- __gthread_mutex_unlock (&u->lock);
- if (predec_waiting_locked (u) == 0)
- free (u);
- goto retry;
- }
-
- dec_waiting_unlocked (u);
- }
- return u;
-}
-
-static gfc_unit *
-flush_all_units_1 (gfc_unit *u, int min_unit)
-{
- while (u != NULL)
- {
- if (u->unit_number > min_unit)
- {
- gfc_unit *r = flush_all_units_1 (u->left, min_unit);
- if (r != NULL)
- return r;
- }
- if (u->unit_number >= min_unit)
- {
- if (__gthread_mutex_trylock (&u->lock))
- return u;
- if (u->s)
- sflush (u->s);
- __gthread_mutex_unlock (&u->lock);
- }
- u = u->right;
- }
- return NULL;
-}
-
-void
-flush_all_units (void)
-{
- gfc_unit *u;
- int min_unit = 0;
-
- __gthread_mutex_lock (&unit_lock);
- do
- {
- u = flush_all_units_1 (unit_root, min_unit);
- if (u != NULL)
- inc_waiting_locked (u);
- __gthread_mutex_unlock (&unit_lock);
- if (u == NULL)
- return;
-
- __gthread_mutex_lock (&u->lock);
-
- min_unit = u->unit_number + 1;
-
- if (u->closed == 0)
- {
- sflush (u->s);
- __gthread_mutex_lock (&unit_lock);
- __gthread_mutex_unlock (&u->lock);
- (void) predec_waiting_locked (u);
- }
- else
- {
- __gthread_mutex_lock (&unit_lock);
- __gthread_mutex_unlock (&u->lock);
- if (predec_waiting_locked (u) == 0)
- free (u);
- }
- }
- while (1);
-}
-
-
-/* delete_file()-- Given a unit structure, delete the file associated
- * with the unit. Returns nonzero if something went wrong. */
-
-int
-delete_file (gfc_unit * u)
-{
- char path[min(PATH_MAX, u->file_len + 1)];
- int err = unpack_filename (path, u->file, u->file_len);
-
- if (err)
- { /* Shouldn't be possible */
- errno = err;
- return 1;
- }
-
- return unlink (path);
-}
-
-
-/* file_exists()-- Returns nonzero if the current filename exists on
- * the system */
-
-int
-file_exists (const char *file, gfc_charlen_type file_len)
-{
- char path[min(PATH_MAX, file_len + 1)];
-
- if (unpack_filename (path, file, file_len))
- return 0;
-
- return !(access (path, F_OK));
-}
-
-
-/* file_size()-- Returns the size of the file. */
-
-GFC_IO_INT
-file_size (const char *file, gfc_charlen_type file_len)
-{
- char path[min(PATH_MAX, file_len + 1)];
- struct stat statbuf;
-
- if (unpack_filename (path, file, file_len))
- return -1;
-
- if (stat (path, &statbuf) < 0)
- return -1;
-
- return (GFC_IO_INT) statbuf.st_size;
-}
-
-static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
-
-/* inquire_sequential()-- Given a fortran string, determine if the
- * file is suitable for sequential access. Returns a C-style
- * string. */
-
-const char *
-inquire_sequential (const char *string, int len)
-{
- char path[min(PATH_MAX, len + 1)];
- struct stat statbuf;
-
- if (string == NULL ||
- unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
- return unknown;
-
- if (S_ISREG (statbuf.st_mode) ||
- S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
- return unknown;
-
- if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
- return no;
-
- return unknown;
-}
-
-
-/* inquire_direct()-- Given a fortran string, determine if the file is
- * suitable for direct access. Returns a C-style string. */
-
-const char *
-inquire_direct (const char *string, int len)
-{
- char path[min(PATH_MAX, len + 1)];
- struct stat statbuf;
-
- if (string == NULL ||
- unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
- return unknown;
-
- if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
- return unknown;
-
- if (S_ISDIR (statbuf.st_mode) ||
- S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
- return no;
-
- return unknown;
-}
-
-
-/* inquire_formatted()-- Given a fortran string, determine if the file
- * is suitable for formatted form. Returns a C-style string. */
-
-const char *
-inquire_formatted (const char *string, int len)
-{
- char path[min(PATH_MAX, len + 1)];
- struct stat statbuf;
-
- if (string == NULL ||
- unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
- return unknown;
-
- if (S_ISREG (statbuf.st_mode) ||
- S_ISBLK (statbuf.st_mode) ||
- S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
- return unknown;
-
- if (S_ISDIR (statbuf.st_mode))
- return no;
-
- return unknown;
-}
-
-
-/* inquire_unformatted()-- Given a fortran string, determine if the file
- * is suitable for unformatted form. Returns a C-style string. */
-
-const char *
-inquire_unformatted (const char *string, int len)
-{
- return inquire_formatted (string, len);
-}
-
-
-/* inquire_access()-- Given a fortran string, determine if the file is
- * suitable for access. */
-
-static const char *
-inquire_access (const char *string, int len, int mode)
-{
- char path[min(PATH_MAX, len + 1)];
-
- if (string == NULL || unpack_filename (path, string, len) ||
- access (path, mode) < 0)
- return no;
-
- return yes;
-}
-
-
-/* inquire_read()-- Given a fortran string, determine if the file is
- * suitable for READ access. */
-
-const char *
-inquire_read (const char *string, int len)
-{
- return inquire_access (string, len, R_OK);
-}
-
-
-/* inquire_write()-- Given a fortran string, determine if the file is
- * suitable for READ access. */
-
-const char *
-inquire_write (const char *string, int len)
-{
- return inquire_access (string, len, W_OK);
-}
-
-
-/* inquire_readwrite()-- Given a fortran string, determine if the file is
- * suitable for read and write access. */
-
-const char *
-inquire_readwrite (const char *string, int len)
-{
- return inquire_access (string, len, R_OK | W_OK);
-}
-
-
-int
-stream_isatty (stream *s)
-{
- return isatty (((unix_stream *) s)->fd);
-}
-
-int
-stream_ttyname (stream *s __attribute__ ((unused)),
- char * buf __attribute__ ((unused)),
- size_t buflen __attribute__ ((unused)))
-{
-#ifdef HAVE_TTYNAME_R
- return ttyname_r (((unix_stream *) s)->fd, buf, buflen);
-#elif defined HAVE_TTYNAME
- char *p;
- size_t plen;
- p = ttyname (((unix_stream *) s)->fd);
- if (!p)
- return errno;
- plen = strlen (p);
- if (buflen < plen)
- plen = buflen;
- memcpy (buf, p, plen);
- return 0;
-#else
- return ENOSYS;
-#endif
-}
-
-
-
-
-/* How files are stored: This is an operating-system specific issue,
- and therefore belongs here. There are three cases to consider.
-
- Direct Access:
- Records are written as block of bytes corresponding to the record
- length of the file. This goes for both formatted and unformatted
- records. Positioning is done explicitly for each data transfer,
- so positioning is not much of an issue.
-
- Sequential Formatted:
- Records are separated by newline characters. The newline character
- is prohibited from appearing in a string. If it does, this will be
- messed up on the next read. End of file is also the end of a record.
-
- Sequential Unformatted:
- In this case, we are merely copying bytes to and from main storage,
- yet we need to keep track of varying record lengths. We adopt
- the solution used by f2c. Each record contains a pair of length
- markers:
-
- Length of record n in bytes
- Data of record n
- Length of record n in bytes
-
- Length of record n+1 in bytes
- Data of record n+1
- Length of record n+1 in bytes
-
- The length is stored at the end of a record to allow backspacing to the
- previous record. Between data transfer statements, the file pointer
- is left pointing to the first length of the current record.
-
- ENDFILE records are never explicitly stored.
-
-*/
diff --git a/gcc-4.8.1/libgfortran/io/unix.h b/gcc-4.8.1/libgfortran/io/unix.h
deleted file mode 100644
index bf59a8ee1..000000000
--- a/gcc-4.8.1/libgfortran/io/unix.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/* Copyright (C) 2009-2013 Free Software Foundation, Inc.
- Contributed by Janne Blomqvist
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef GFOR_UNIX_H
-#define GFOR_UNIX_H
-
-#include "io.h"
-
-struct stream_vtable
-{
- ssize_t (* const read) (struct stream *, void *, ssize_t);
- ssize_t (* const write) (struct stream *, const void *, ssize_t);
- gfc_offset (* const seek) (struct stream *, gfc_offset, int);
- gfc_offset (* const tell) (struct stream *);
- gfc_offset (* const size) (struct stream *);
- /* Avoid keyword truncate due to AIX namespace collision. */
- int (* const trunc) (struct stream *, gfc_offset);
- int (* const flush) (struct stream *);
- int (* const close) (struct stream *);
-};
-
-struct stream
-{
- const struct stream_vtable *vptr;
-};
-
-/* Inline functions for doing file I/O given a stream. */
-static inline ssize_t
-sread (stream * s, void * buf, ssize_t nbyte)
-{
- return s->vptr->read (s, buf, nbyte);
-}
-
-static inline ssize_t
-swrite (stream * s, const void * buf, ssize_t nbyte)
-{
- return s->vptr->write (s, buf, nbyte);
-}
-
-static inline gfc_offset
-sseek (stream * s, gfc_offset offset, int whence)
-{
- return s->vptr->seek (s, offset, whence);
-}
-
-static inline gfc_offset
-stell (stream * s)
-{
- return s->vptr->tell (s);
-}
-
-static inline gfc_offset
-ssize (stream * s)
-{
- return s->vptr->size (s);
-}
-
-static inline int
-struncate (stream * s, gfc_offset length)
-{
- return s->vptr->trunc (s, length);
-}
-
-static inline int
-sflush (stream * s)
-{
- return s->vptr->flush (s);
-}
-
-static inline int
-sclose (stream * s)
-{
- return s->vptr->close (s);
-}
-
-
-extern int compare_files (stream *, stream *);
-internal_proto(compare_files);
-
-extern stream *open_external (st_parameter_open *, unit_flags *);
-internal_proto(open_external);
-
-extern stream *open_internal (char *, int, gfc_offset);
-internal_proto(open_internal);
-
-extern stream *open_internal4 (char *, int, gfc_offset);
-internal_proto(open_internal4);
-
-extern char * mem_alloc_w (stream *, int *);
-internal_proto(mem_alloc_w);
-
-extern char * mem_alloc_r (stream *, int *);
-internal_proto(mem_alloc_r);
-
-extern gfc_char4_t * mem_alloc_w4 (stream *, int *);
-internal_proto(mem_alloc_w4);
-
-extern char * mem_alloc_r4 (stream *, int *);
-internal_proto(mem_alloc_r4);
-
-extern stream *input_stream (void);
-internal_proto(input_stream);
-
-extern stream *output_stream (void);
-internal_proto(output_stream);
-
-extern stream *error_stream (void);
-internal_proto(error_stream);
-
-extern int compare_file_filename (gfc_unit *, const char *, int);
-internal_proto(compare_file_filename);
-
-extern gfc_unit *find_file (const char *file, gfc_charlen_type file_len);
-internal_proto(find_file);
-
-extern int delete_file (gfc_unit *);
-internal_proto(delete_file);
-
-extern int file_exists (const char *file, gfc_charlen_type file_len);
-internal_proto(file_exists);
-
-extern GFC_IO_INT file_size (const char *file, gfc_charlen_type file_len);
-internal_proto(file_size);
-
-extern const char *inquire_sequential (const char *, int);
-internal_proto(inquire_sequential);
-
-extern const char *inquire_direct (const char *, int);
-internal_proto(inquire_direct);
-
-extern const char *inquire_formatted (const char *, int);
-internal_proto(inquire_formatted);
-
-extern const char *inquire_unformatted (const char *, int);
-internal_proto(inquire_unformatted);
-
-extern const char *inquire_read (const char *, int);
-internal_proto(inquire_read);
-
-extern const char *inquire_write (const char *, int);
-internal_proto(inquire_write);
-
-extern const char *inquire_readwrite (const char *, int);
-internal_proto(inquire_readwrite);
-
-extern void flush_if_preconnected (stream *);
-internal_proto(flush_if_preconnected);
-
-extern int stream_isatty (stream *);
-internal_proto(stream_isatty);
-
-#ifndef TTY_NAME_MAX
-#ifdef _POSIX_TTY_NAME_MAX
-#define TTY_NAME_MAX _POSIX_TTY_NAME_MAX
-#else
-/* sysconf(_SC_TTY_NAME_MAX) = 32 which should be enough. */
-#define TTY_NAME_MAX 32
-#endif
-#endif
-
-extern int stream_ttyname (stream *, char *, size_t);
-internal_proto(stream_ttyname);
-
-extern int unpack_filename (char *, const char *, int);
-internal_proto(unpack_filename);
-
-
-#endif
diff --git a/gcc-4.8.1/libgfortran/io/write.c b/gcc-4.8.1/libgfortran/io/write.c
deleted file mode 100644
index f17528edc..000000000
--- a/gcc-4.8.1/libgfortran/io/write.c
+++ /dev/null
@@ -1,2006 +0,0 @@
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- Namelist output contributed by Paul Thomas
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "io.h"
-#include "format.h"
-#include "unix.h"
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <errno.h>
-#define star_fill(p, n) memset(p, '*', n)
-
-typedef unsigned char uchar;
-
-/* Helper functions for character(kind=4) internal units. These are needed
- by write_float.def. */
-
-static void
-memcpy4 (gfc_char4_t *dest, const char *source, int k)
-{
- int j;
-
- const char *p = source;
- for (j = 0; j < k; j++)
- *dest++ = (gfc_char4_t) *p++;
-}
-
-/* This include contains the heart and soul of formatted floating point. */
-#include "write_float.def"
-
-/* Write out default char4. */
-
-static void
-write_default_char4 (st_parameter_dt *dtp, const gfc_char4_t *source,
- int src_len, int w_len)
-{
- char *p;
- int j, k = 0;
- gfc_char4_t c;
- uchar d;
-
- /* Take care of preceding blanks. */
- if (w_len > src_len)
- {
- k = w_len - src_len;
- p = write_block (dtp, k);
- if (p == NULL)
- return;
- if (is_char4_unit (dtp))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, ' ', k);
- }
- else
- memset (p, ' ', k);
- }
-
- /* Get ready to handle delimiters if needed. */
- switch (dtp->u.p.current_unit->delim_status)
- {
- case DELIM_APOSTROPHE:
- d = '\'';
- break;
- case DELIM_QUOTE:
- d = '"';
- break;
- default:
- d = ' ';
- break;
- }
-
- /* Now process the remaining characters, one at a time. */
- for (j = 0; j < src_len; j++)
- {
- c = source[j];
- if (is_char4_unit (dtp))
- {
- gfc_char4_t *q;
- /* Handle delimiters if any. */
- if (c == d && d != ' ')
- {
- p = write_block (dtp, 2);
- if (p == NULL)
- return;
- q = (gfc_char4_t *) p;
- *q++ = c;
- }
- else
- {
- p = write_block (dtp, 1);
- if (p == NULL)
- return;
- q = (gfc_char4_t *) p;
- }
- *q = c;
- }
- else
- {
- /* Handle delimiters if any. */
- if (c == d && d != ' ')
- {
- p = write_block (dtp, 2);
- if (p == NULL)
- return;
- *p++ = (uchar) c;
- }
- else
- {
- p = write_block (dtp, 1);
- if (p == NULL)
- return;
- }
- *p = c > 255 ? '?' : (uchar) c;
- }
- }
-}
-
-
-/* Write out UTF-8 converted from char4. */
-
-static void
-write_utf8_char4 (st_parameter_dt *dtp, gfc_char4_t *source,
- int src_len, int w_len)
-{
- char *p;
- int j, k = 0;
- gfc_char4_t c;
- static const uchar masks[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
- static const uchar limits[6] = { 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
- int nbytes;
- uchar buf[6], d, *q;
-
- /* Take care of preceding blanks. */
- if (w_len > src_len)
- {
- k = w_len - src_len;
- p = write_block (dtp, k);
- if (p == NULL)
- return;
- memset (p, ' ', k);
- }
-
- /* Get ready to handle delimiters if needed. */
- switch (dtp->u.p.current_unit->delim_status)
- {
- case DELIM_APOSTROPHE:
- d = '\'';
- break;
- case DELIM_QUOTE:
- d = '"';
- break;
- default:
- d = ' ';
- break;
- }
-
- /* Now process the remaining characters, one at a time. */
- for (j = k; j < src_len; j++)
- {
- c = source[j];
- if (c < 0x80)
- {
- /* Handle the delimiters if any. */
- if (c == d && d != ' ')
- {
- p = write_block (dtp, 2);
- if (p == NULL)
- return;
- *p++ = (uchar) c;
- }
- else
- {
- p = write_block (dtp, 1);
- if (p == NULL)
- return;
- }
- *p = (uchar) c;
- }
- else
- {
- /* Convert to UTF-8 sequence. */
- nbytes = 1;
- q = &buf[6];
-
- do
- {
- *--q = ((c & 0x3F) | 0x80);
- c >>= 6;
- nbytes++;
- }
- while (c >= 0x3F || (c & limits[nbytes-1]));
-
- *--q = (c | masks[nbytes-1]);
-
- p = write_block (dtp, nbytes);
- if (p == NULL)
- return;
-
- while (q < &buf[6])
- *p++ = *q++;
- }
- }
-}
-
-
-void
-write_a (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
-{
- int wlen;
- char *p;
-
- wlen = f->u.string.length < 0
- || (f->format == FMT_G && f->u.string.length == 0)
- ? len : f->u.string.length;
-
-#ifdef HAVE_CRLF
- /* If this is formatted STREAM IO convert any embedded line feed characters
- to CR_LF on systems that use that sequence for newlines. See F2003
- Standard sections 10.6.3 and 9.9 for further information. */
- if (is_stream_io (dtp))
- {
- const char crlf[] = "\r\n";
- int i, q, bytes;
- q = bytes = 0;
-
- /* Write out any padding if needed. */
- if (len < wlen)
- {
- p = write_block (dtp, wlen - len);
- if (p == NULL)
- return;
- memset (p, ' ', wlen - len);
- }
-
- /* Scan the source string looking for '\n' and convert it if found. */
- for (i = 0; i < wlen; i++)
- {
- if (source[i] == '\n')
- {
- /* Write out the previously scanned characters in the string. */
- if (bytes > 0)
- {
- p = write_block (dtp, bytes);
- if (p == NULL)
- return;
- memcpy (p, &source[q], bytes);
- q += bytes;
- bytes = 0;
- }
-
- /* Write out the CR_LF sequence. */
- q++;
- p = write_block (dtp, 2);
- if (p == NULL)
- return;
- memcpy (p, crlf, 2);
- }
- else
- bytes++;
- }
-
- /* Write out any remaining bytes if no LF was found. */
- if (bytes > 0)
- {
- p = write_block (dtp, bytes);
- if (p == NULL)
- return;
- memcpy (p, &source[q], bytes);
- }
- }
- else
- {
-#endif
- p = write_block (dtp, wlen);
- if (p == NULL)
- return;
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- if (wlen < len)
- memcpy4 (p4, source, wlen);
- else
- {
- memset4 (p4, ' ', wlen - len);
- memcpy4 (p4 + wlen - len, source, len);
- }
- return;
- }
-
- if (wlen < len)
- memcpy (p, source, wlen);
- else
- {
- memset (p, ' ', wlen - len);
- memcpy (p + wlen - len, source, len);
- }
-#ifdef HAVE_CRLF
- }
-#endif
-}
-
-
-/* The primary difference between write_a_char4 and write_a is that we have to
- deal with writing from the first byte of the 4-byte character and pay
- attention to the most significant bytes. For ENCODING="default" write the
- lowest significant byte. If the 3 most significant bytes contain
- non-zero values, emit a '?'. For ENCODING="utf-8", convert the UCS-32 value
- to the UTF-8 encoded string before writing out. */
-
-void
-write_a_char4 (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
-{
- int wlen;
- gfc_char4_t *q;
-
- wlen = f->u.string.length < 0
- || (f->format == FMT_G && f->u.string.length == 0)
- ? len : f->u.string.length;
-
- q = (gfc_char4_t *) source;
-#ifdef HAVE_CRLF
- /* If this is formatted STREAM IO convert any embedded line feed characters
- to CR_LF on systems that use that sequence for newlines. See F2003
- Standard sections 10.6.3 and 9.9 for further information. */
- if (is_stream_io (dtp))
- {
- const gfc_char4_t crlf[] = {0x000d,0x000a};
- int i, bytes;
- gfc_char4_t *qq;
- bytes = 0;
-
- /* Write out any padding if needed. */
- if (len < wlen)
- {
- char *p;
- p = write_block (dtp, wlen - len);
- if (p == NULL)
- return;
- memset (p, ' ', wlen - len);
- }
-
- /* Scan the source string looking for '\n' and convert it if found. */
- qq = (gfc_char4_t *) source;
- for (i = 0; i < wlen; i++)
- {
- if (qq[i] == '\n')
- {
- /* Write out the previously scanned characters in the string. */
- if (bytes > 0)
- {
- if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
- write_utf8_char4 (dtp, q, bytes, 0);
- else
- write_default_char4 (dtp, q, bytes, 0);
- bytes = 0;
- }
-
- /* Write out the CR_LF sequence. */
- write_default_char4 (dtp, crlf, 2, 0);
- }
- else
- bytes++;
- }
-
- /* Write out any remaining bytes if no LF was found. */
- if (bytes > 0)
- {
- if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
- write_utf8_char4 (dtp, q, bytes, 0);
- else
- write_default_char4 (dtp, q, bytes, 0);
- }
- }
- else
- {
-#endif
- if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
- write_utf8_char4 (dtp, q, len, wlen);
- else
- write_default_char4 (dtp, q, len, wlen);
-#ifdef HAVE_CRLF
- }
-#endif
-}
-
-
-static GFC_INTEGER_LARGEST
-extract_int (const void *p, int len)
-{
- GFC_INTEGER_LARGEST i = 0;
-
- if (p == NULL)
- return i;
-
- switch (len)
- {
- case 1:
- {
- GFC_INTEGER_1 tmp;
- memcpy ((void *) &tmp, p, len);
- i = tmp;
- }
- break;
- case 2:
- {
- GFC_INTEGER_2 tmp;
- memcpy ((void *) &tmp, p, len);
- i = tmp;
- }
- break;
- case 4:
- {
- GFC_INTEGER_4 tmp;
- memcpy ((void *) &tmp, p, len);
- i = tmp;
- }
- break;
- case 8:
- {
- GFC_INTEGER_8 tmp;
- memcpy ((void *) &tmp, p, len);
- i = tmp;
- }
- break;
-#ifdef HAVE_GFC_INTEGER_16
- case 16:
- {
- GFC_INTEGER_16 tmp;
- memcpy ((void *) &tmp, p, len);
- i = tmp;
- }
- break;
-#endif
- default:
- internal_error (NULL, "bad integer kind");
- }
-
- return i;
-}
-
-static GFC_UINTEGER_LARGEST
-extract_uint (const void *p, int len)
-{
- GFC_UINTEGER_LARGEST i = 0;
-
- if (p == NULL)
- return i;
-
- switch (len)
- {
- case 1:
- {
- GFC_INTEGER_1 tmp;
- memcpy ((void *) &tmp, p, len);
- i = (GFC_UINTEGER_1) tmp;
- }
- break;
- case 2:
- {
- GFC_INTEGER_2 tmp;
- memcpy ((void *) &tmp, p, len);
- i = (GFC_UINTEGER_2) tmp;
- }
- break;
- case 4:
- {
- GFC_INTEGER_4 tmp;
- memcpy ((void *) &tmp, p, len);
- i = (GFC_UINTEGER_4) tmp;
- }
- break;
- case 8:
- {
- GFC_INTEGER_8 tmp;
- memcpy ((void *) &tmp, p, len);
- i = (GFC_UINTEGER_8) tmp;
- }
- break;
-#ifdef HAVE_GFC_INTEGER_16
- case 10:
- case 16:
- {
- GFC_INTEGER_16 tmp = 0;
- memcpy ((void *) &tmp, p, len);
- i = (GFC_UINTEGER_16) tmp;
- }
- break;
-#endif
- default:
- internal_error (NULL, "bad integer kind");
- }
-
- return i;
-}
-
-
-void
-write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
-{
- char *p;
- int wlen;
- GFC_INTEGER_LARGEST n;
-
- wlen = (f->format == FMT_G && f->u.w == 0) ? 1 : f->u.w;
-
- p = write_block (dtp, wlen);
- if (p == NULL)
- return;
-
- n = extract_int (source, len);
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, ' ', wlen -1);
- p4[wlen - 1] = (n) ? 'T' : 'F';
- return;
- }
-
- memset (p, ' ', wlen -1);
- p[wlen - 1] = (n) ? 'T' : 'F';
-}
-
-
-static void
-write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n)
-{
- int w, m, digits, nzero, nblank;
- char *p;
-
- w = f->u.integer.w;
- m = f->u.integer.m;
-
- /* Special case: */
-
- if (m == 0 && n == 0)
- {
- if (w == 0)
- w = 1;
-
- p = write_block (dtp, w);
- if (p == NULL)
- return;
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, ' ', w);
- }
- else
- memset (p, ' ', w);
- goto done;
- }
-
- digits = strlen (q);
-
- /* Select a width if none was specified. The idea here is to always
- print something. */
-
- if (w == 0)
- w = ((digits < m) ? m : digits);
-
- p = write_block (dtp, w);
- if (p == NULL)
- return;
-
- nzero = 0;
- if (digits < m)
- nzero = m - digits;
-
- /* See if things will work. */
-
- nblank = w - (nzero + digits);
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- if (nblank < 0)
- {
- memset4 (p4, '*', w);
- return;
- }
-
- if (!dtp->u.p.no_leading_blank)
- {
- memset4 (p4, ' ', nblank);
- q += nblank;
- memset4 (p4, '0', nzero);
- q += nzero;
- memcpy4 (p4, q, digits);
- }
- else
- {
- memset4 (p4, '0', nzero);
- q += nzero;
- memcpy4 (p4, q, digits);
- q += digits;
- memset4 (p4, ' ', nblank);
- dtp->u.p.no_leading_blank = 0;
- }
- return;
- }
-
- if (nblank < 0)
- {
- star_fill (p, w);
- goto done;
- }
-
- if (!dtp->u.p.no_leading_blank)
- {
- memset (p, ' ', nblank);
- p += nblank;
- memset (p, '0', nzero);
- p += nzero;
- memcpy (p, q, digits);
- }
- else
- {
- memset (p, '0', nzero);
- p += nzero;
- memcpy (p, q, digits);
- p += digits;
- memset (p, ' ', nblank);
- dtp->u.p.no_leading_blank = 0;
- }
-
- done:
- return;
-}
-
-static void
-write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
- int len,
- const char *(*conv) (GFC_INTEGER_LARGEST, char *, size_t))
-{
- GFC_INTEGER_LARGEST n = 0;
- int w, m, digits, nsign, nzero, nblank;
- char *p;
- const char *q;
- sign_t sign;
- char itoa_buf[GFC_BTOA_BUF_SIZE];
-
- w = f->u.integer.w;
- m = f->format == FMT_G ? -1 : f->u.integer.m;
-
- n = extract_int (source, len);
-
- /* Special case: */
- if (m == 0 && n == 0)
- {
- if (w == 0)
- w = 1;
-
- p = write_block (dtp, w);
- if (p == NULL)
- return;
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, ' ', w);
- }
- else
- memset (p, ' ', w);
- goto done;
- }
-
- sign = calculate_sign (dtp, n < 0);
- if (n < 0)
- n = -n;
- nsign = sign == S_NONE ? 0 : 1;
-
- /* conv calls itoa which sets the negative sign needed
- by write_integer. The sign '+' or '-' is set below based on sign
- calculated above, so we just point past the sign in the string
- before proceeding to avoid double signs in corner cases.
- (see PR38504) */
- q = conv (n, itoa_buf, sizeof (itoa_buf));
- if (*q == '-')
- q++;
-
- digits = strlen (q);
-
- /* Select a width if none was specified. The idea here is to always
- print something. */
-
- if (w == 0)
- w = ((digits < m) ? m : digits) + nsign;
-
- p = write_block (dtp, w);
- if (p == NULL)
- return;
-
- nzero = 0;
- if (digits < m)
- nzero = m - digits;
-
- /* See if things will work. */
-
- nblank = w - (nsign + nzero + digits);
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t * p4 = (gfc_char4_t *) p;
- if (nblank < 0)
- {
- memset4 (p4, '*', w);
- goto done;
- }
-
- memset4 (p4, ' ', nblank);
- p4 += nblank;
-
- switch (sign)
- {
- case S_PLUS:
- *p4++ = '+';
- break;
- case S_MINUS:
- *p4++ = '-';
- break;
- case S_NONE:
- break;
- }
-
- memset4 (p4, '0', nzero);
- p4 += nzero;
-
- memcpy4 (p4, q, digits);
- return;
- }
-
- if (nblank < 0)
- {
- star_fill (p, w);
- goto done;
- }
-
- memset (p, ' ', nblank);
- p += nblank;
-
- switch (sign)
- {
- case S_PLUS:
- *p++ = '+';
- break;
- case S_MINUS:
- *p++ = '-';
- break;
- case S_NONE:
- break;
- }
-
- memset (p, '0', nzero);
- p += nzero;
-
- memcpy (p, q, digits);
-
- done:
- return;
-}
-
-
-/* Convert unsigned octal to ascii. */
-
-static const char *
-otoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
-{
- char *p;
-
- assert (len >= GFC_OTOA_BUF_SIZE);
-
- if (n == 0)
- return "0";
-
- p = buffer + GFC_OTOA_BUF_SIZE - 1;
- *p = '\0';
-
- while (n != 0)
- {
- *--p = '0' + (n & 7);
- n >>= 3;
- }
-
- return p;
-}
-
-
-/* Convert unsigned binary to ascii. */
-
-static const char *
-btoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
-{
- char *p;
-
- assert (len >= GFC_BTOA_BUF_SIZE);
-
- if (n == 0)
- return "0";
-
- p = buffer + GFC_BTOA_BUF_SIZE - 1;
- *p = '\0';
-
- while (n != 0)
- {
- *--p = '0' + (n & 1);
- n >>= 1;
- }
-
- return p;
-}
-
-/* The following three functions, btoa_big, otoa_big, and ztoa_big, are needed
- to convert large reals with kind sizes that exceed the largest integer type
- available on certain platforms. In these cases, byte by byte conversion is
- performed. Endianess is taken into account. */
-
-/* Conversion to binary. */
-
-static const char *
-btoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
-{
- char *q;
- int i, j;
-
- q = buffer;
- if (big_endian)
- {
- const char *p = s;
- for (i = 0; i < len; i++)
- {
- char c = *p;
-
- /* Test for zero. Needed by write_boz later. */
- if (*p != 0)
- *n = 1;
-
- for (j = 0; j < 8; j++)
- {
- *q++ = (c & 128) ? '1' : '0';
- c <<= 1;
- }
- p++;
- }
- }
- else
- {
- const char *p = s + len - 1;
- for (i = 0; i < len; i++)
- {
- char c = *p;
-
- /* Test for zero. Needed by write_boz later. */
- if (*p != 0)
- *n = 1;
-
- for (j = 0; j < 8; j++)
- {
- *q++ = (c & 128) ? '1' : '0';
- c <<= 1;
- }
- p--;
- }
- }
-
- *q = '\0';
-
- if (*n == 0)
- return "0";
-
- /* Move past any leading zeros. */
- while (*buffer == '0')
- buffer++;
-
- return buffer;
-
-}
-
-/* Conversion to octal. */
-
-static const char *
-otoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
-{
- char *q;
- int i, j, k;
- uint8_t octet;
-
- q = buffer + GFC_OTOA_BUF_SIZE - 1;
- *q = '\0';
- i = k = octet = 0;
-
- if (big_endian)
- {
- const char *p = s + len - 1;
- char c = *p;
- while (i < len)
- {
- /* Test for zero. Needed by write_boz later. */
- if (*p != 0)
- *n = 1;
-
- for (j = 0; j < 3 && i < len; j++)
- {
- octet |= (c & 1) << j;
- c >>= 1;
- if (++k > 7)
- {
- i++;
- k = 0;
- c = *--p;
- }
- }
- *--q = '0' + octet;
- octet = 0;
- }
- }
- else
- {
- const char *p = s;
- char c = *p;
- while (i < len)
- {
- /* Test for zero. Needed by write_boz later. */
- if (*p != 0)
- *n = 1;
-
- for (j = 0; j < 3 && i < len; j++)
- {
- octet |= (c & 1) << j;
- c >>= 1;
- if (++k > 7)
- {
- i++;
- k = 0;
- c = *++p;
- }
- }
- *--q = '0' + octet;
- octet = 0;
- }
- }
-
- if (*n == 0)
- return "0";
-
- /* Move past any leading zeros. */
- while (*q == '0')
- q++;
-
- return q;
-}
-
-/* Conversion to hexidecimal. */
-
-static const char *
-ztoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
-{
- static char a[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-
- char *q;
- uint8_t h, l;
- int i;
-
- q = buffer;
-
- if (big_endian)
- {
- const char *p = s;
- for (i = 0; i < len; i++)
- {
- /* Test for zero. Needed by write_boz later. */
- if (*p != 0)
- *n = 1;
-
- h = (*p >> 4) & 0x0F;
- l = *p++ & 0x0F;
- *q++ = a[h];
- *q++ = a[l];
- }
- }
- else
- {
- const char *p = s + len - 1;
- for (i = 0; i < len; i++)
- {
- /* Test for zero. Needed by write_boz later. */
- if (*p != 0)
- *n = 1;
-
- h = (*p >> 4) & 0x0F;
- l = *p-- & 0x0F;
- *q++ = a[h];
- *q++ = a[l];
- }
- }
-
- *q = '\0';
-
- if (*n == 0)
- return "0";
-
- /* Move past any leading zeros. */
- while (*buffer == '0')
- buffer++;
-
- return buffer;
-}
-
-/* gfc_itoa()-- Integer to decimal conversion.
- The itoa function is a widespread non-standard extension to standard
- C, often declared in <stdlib.h>. Even though the itoa defined here
- is a static function we take care not to conflict with any prior
- non-static declaration. Hence the 'gfc_' prefix, which is normally
- reserved for functions with external linkage. */
-
-static const char *
-gfc_itoa (GFC_INTEGER_LARGEST n, char *buffer, size_t len)
-{
- int negative;
- char *p;
- GFC_UINTEGER_LARGEST t;
-
- assert (len >= GFC_ITOA_BUF_SIZE);
-
- if (n == 0)
- return "0";
-
- negative = 0;
- t = n;
- if (n < 0)
- {
- negative = 1;
- t = -n; /*must use unsigned to protect from overflow*/
- }
-
- p = buffer + GFC_ITOA_BUF_SIZE - 1;
- *p = '\0';
-
- while (t != 0)
- {
- *--p = '0' + (t % 10);
- t /= 10;
- }
-
- if (negative)
- *--p = '-';
- return p;
-}
-
-
-void
-write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
-{
- write_decimal (dtp, f, p, len, (void *) gfc_itoa);
-}
-
-
-void
-write_b (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
-{
- const char *p;
- char itoa_buf[GFC_BTOA_BUF_SIZE];
- GFC_UINTEGER_LARGEST n = 0;
-
- if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
- {
- p = btoa_big (source, itoa_buf, len, &n);
- write_boz (dtp, f, p, n);
- }
- else
- {
- n = extract_uint (source, len);
- p = btoa (n, itoa_buf, sizeof (itoa_buf));
- write_boz (dtp, f, p, n);
- }
-}
-
-
-void
-write_o (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
-{
- const char *p;
- char itoa_buf[GFC_OTOA_BUF_SIZE];
- GFC_UINTEGER_LARGEST n = 0;
-
- if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
- {
- p = otoa_big (source, itoa_buf, len, &n);
- write_boz (dtp, f, p, n);
- }
- else
- {
- n = extract_uint (source, len);
- p = otoa (n, itoa_buf, sizeof (itoa_buf));
- write_boz (dtp, f, p, n);
- }
-}
-
-void
-write_z (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
-{
- const char *p;
- char itoa_buf[GFC_XTOA_BUF_SIZE];
- GFC_UINTEGER_LARGEST n = 0;
-
- if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
- {
- p = ztoa_big (source, itoa_buf, len, &n);
- write_boz (dtp, f, p, n);
- }
- else
- {
- n = extract_uint (source, len);
- p = gfc_xtoa (n, itoa_buf, sizeof (itoa_buf));
- write_boz (dtp, f, p, n);
- }
-}
-
-
-void
-write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
-{
- write_float (dtp, f, p, len, 0);
-}
-
-
-void
-write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
-{
- write_float (dtp, f, p, len, 0);
-}
-
-
-void
-write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
-{
- write_float (dtp, f, p, len, 0);
-}
-
-
-void
-write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
-{
- write_float (dtp, f, p, len, 0);
-}
-
-
-void
-write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
-{
- write_float (dtp, f, p, len, 0);
-}
-
-
-/* Take care of the X/TR descriptor. */
-
-void
-write_x (st_parameter_dt *dtp, int len, int nspaces)
-{
- char *p;
-
- p = write_block (dtp, len);
- if (p == NULL)
- return;
- if (nspaces > 0 && len - nspaces >= 0)
- {
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (&p4[len - nspaces], ' ', nspaces);
- }
- else
- memset (&p[len - nspaces], ' ', nspaces);
- }
-}
-
-
-/* List-directed writing. */
-
-
-/* Write a single character to the output. Returns nonzero if
- something goes wrong. */
-
-static int
-write_char (st_parameter_dt *dtp, int c)
-{
- char *p;
-
- p = write_block (dtp, 1);
- if (p == NULL)
- return 1;
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- *p4 = c;
- return 0;
- }
-
- *p = (uchar) c;
-
- return 0;
-}
-
-
-/* Write a list-directed logical value. */
-
-static void
-write_logical (st_parameter_dt *dtp, const char *source, int length)
-{
- write_char (dtp, extract_int (source, length) ? 'T' : 'F');
-}
-
-
-/* Write a list-directed integer value. */
-
-static void
-write_integer (st_parameter_dt *dtp, const char *source, int length)
-{
- char *p;
- const char *q;
- int digits;
- int width;
- char itoa_buf[GFC_ITOA_BUF_SIZE];
-
- q = gfc_itoa (extract_int (source, length), itoa_buf, sizeof (itoa_buf));
-
- switch (length)
- {
- case 1:
- width = 4;
- break;
-
- case 2:
- width = 6;
- break;
-
- case 4:
- width = 11;
- break;
-
- case 8:
- width = 20;
- break;
-
- default:
- width = 0;
- break;
- }
-
- digits = strlen (q);
-
- if (width < digits)
- width = digits;
- p = write_block (dtp, width);
- if (p == NULL)
- return;
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- if (dtp->u.p.no_leading_blank)
- {
- memcpy4 (p4, q, digits);
- memset4 (p4 + digits, ' ', width - digits);
- }
- else
- {
- memset4 (p4, ' ', width - digits);
- memcpy4 (p4 + width - digits, q, digits);
- }
- return;
- }
-
- if (dtp->u.p.no_leading_blank)
- {
- memcpy (p, q, digits);
- memset (p + digits, ' ', width - digits);
- }
- else
- {
- memset (p, ' ', width - digits);
- memcpy (p + width - digits, q, digits);
- }
-}
-
-
-/* Write a list-directed string. We have to worry about delimiting
- the strings if the file has been opened in that mode. */
-
-static void
-write_character (st_parameter_dt *dtp, const char *source, int kind, int length)
-{
- int i, extra;
- char *p, d;
-
- switch (dtp->u.p.current_unit->delim_status)
- {
- case DELIM_APOSTROPHE:
- d = '\'';
- break;
- case DELIM_QUOTE:
- d = '"';
- break;
- default:
- d = ' ';
- break;
- }
-
- if (kind == 1)
- {
- if (d == ' ')
- extra = 0;
- else
- {
- extra = 2;
-
- for (i = 0; i < length; i++)
- if (source[i] == d)
- extra++;
- }
-
- p = write_block (dtp, length + extra);
- if (p == NULL)
- return;
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t d4 = (gfc_char4_t) d;
- gfc_char4_t *p4 = (gfc_char4_t *) p;
-
- if (d4 == ' ')
- memcpy4 (p4, source, length);
- else
- {
- *p4++ = d4;
-
- for (i = 0; i < length; i++)
- {
- *p4++ = (gfc_char4_t) source[i];
- if (source[i] == d)
- *p4++ = d4;
- }
-
- *p4 = d4;
- }
- return;
- }
-
- if (d == ' ')
- memcpy (p, source, length);
- else
- {
- *p++ = d;
-
- for (i = 0; i < length; i++)
- {
- *p++ = source[i];
- if (source[i] == d)
- *p++ = d;
- }
-
- *p = d;
- }
- }
- else
- {
- if (d == ' ')
- {
- if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
- write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
- else
- write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
- }
- else
- {
- p = write_block (dtp, 1);
- *p = d;
-
- if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
- write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
- else
- write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
-
- p = write_block (dtp, 1);
- *p = d;
- }
- }
-}
-
-
-/* Set an fnode to default format. */
-
-static void
-set_fnode_default (st_parameter_dt *dtp, fnode *f, int length)
-{
- f->format = FMT_G;
- switch (length)
- {
- case 4:
- f->u.real.w = 16;
- f->u.real.d = 9;
- f->u.real.e = 2;
- break;
- case 8:
- f->u.real.w = 25;
- f->u.real.d = 17;
- f->u.real.e = 3;
- break;
- case 10:
- f->u.real.w = 30;
- f->u.real.d = 21;
- f->u.real.e = 4;
- break;
- case 16:
- f->u.real.w = 45;
- f->u.real.d = 36;
- f->u.real.e = 4;
- break;
- default:
- internal_error (&dtp->common, "bad real kind");
- break;
- }
-}
-
-/* Output a real number with default format. To guarantee that a
- binary -> decimal -> binary roundtrip conversion recovers the
- original value, IEEE 754-2008 requires 9, 17, 21 and 36 significant
- digits for REAL kinds 4, 8, 10, and 16, respectively. Thus, we use
- 1PG16.9E2 for REAL(4), 1PG25.17E3 for REAL(8), 1PG30.21E4 for
- REAL(10) and 1PG45.36E4 for REAL(16). The exception is that the
- Fortran standard requires outputting an extra digit when the scale
- factor is 1 and when the magnitude of the value is such that E
- editing is used. However, gfortran compensates for this, and thus
- for list formatted the same number of significant digits is
- generated both when using F and E editing. */
-
-void
-write_real (st_parameter_dt *dtp, const char *source, int length)
-{
- fnode f ;
- int org_scale = dtp->u.p.scale_factor;
- dtp->u.p.scale_factor = 1;
- set_fnode_default (dtp, &f, length);
- write_float (dtp, &f, source , length, 1);
- dtp->u.p.scale_factor = org_scale;
-}
-
-/* Similar to list formatted REAL output, for kPG0 where k > 0 we
- compensate for the extra digit. */
-
-void
-write_real_g0 (st_parameter_dt *dtp, const char *source, int length, int d)
-{
- fnode f;
- int comp_d;
- set_fnode_default (dtp, &f, length);
- if (d > 0)
- f.u.real.d = d;
-
- /* Compensate for extra digits when using scale factor, d is not
- specified, and the magnitude is such that E editing is used. */
- if (dtp->u.p.scale_factor > 0 && d == 0)
- comp_d = 1;
- else
- comp_d = 0;
- dtp->u.p.g0_no_blanks = 1;
- write_float (dtp, &f, source , length, comp_d);
- dtp->u.p.g0_no_blanks = 0;
-}
-
-
-static void
-write_complex (st_parameter_dt *dtp, const char *source, int kind, size_t size)
-{
- char semi_comma =
- dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';';
-
- if (write_char (dtp, '('))
- return;
- write_real (dtp, source, kind);
-
- if (write_char (dtp, semi_comma))
- return;
- write_real (dtp, source + size / 2, kind);
-
- write_char (dtp, ')');
-}
-
-
-/* Write the separator between items. */
-
-static void
-write_separator (st_parameter_dt *dtp)
-{
- char *p;
-
- p = write_block (dtp, options.separator_len);
- if (p == NULL)
- return;
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memcpy4 (p4, options.separator, options.separator_len);
- }
- else
- memcpy (p, options.separator, options.separator_len);
-}
-
-
-/* Write an item with list formatting.
- TODO: handle skipping to the next record correctly, particularly
- with strings. */
-
-static void
-list_formatted_write_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
- size_t size)
-{
- if (dtp->u.p.current_unit == NULL)
- return;
-
- if (dtp->u.p.first_item)
- {
- dtp->u.p.first_item = 0;
- write_char (dtp, ' ');
- }
- else
- {
- if (type != BT_CHARACTER || !dtp->u.p.char_flag ||
- dtp->u.p.current_unit->delim_status != DELIM_NONE)
- write_separator (dtp);
- }
-
- switch (type)
- {
- case BT_INTEGER:
- write_integer (dtp, p, kind);
- break;
- case BT_LOGICAL:
- write_logical (dtp, p, kind);
- break;
- case BT_CHARACTER:
- write_character (dtp, p, kind, size);
- break;
- case BT_REAL:
- write_real (dtp, p, kind);
- break;
- case BT_COMPLEX:
- write_complex (dtp, p, kind, size);
- break;
- default:
- internal_error (&dtp->common, "list_formatted_write(): Bad type");
- }
-
- dtp->u.p.char_flag = (type == BT_CHARACTER);
-}
-
-
-void
-list_formatted_write (st_parameter_dt *dtp, bt type, void *p, int kind,
- size_t size, size_t nelems)
-{
- size_t elem;
- char *tmp;
- size_t stride = type == BT_CHARACTER ?
- size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
-
- tmp = (char *) p;
-
- /* Big loop over all the elements. */
- for (elem = 0; elem < nelems; elem++)
- {
- dtp->u.p.item_count++;
- list_formatted_write_scalar (dtp, type, tmp + elem * stride, kind, size);
- }
-}
-
-/* NAMELIST OUTPUT
-
- nml_write_obj writes a namelist object to the output stream. It is called
- recursively for derived type components:
- obj = is the namelist_info for the current object.
- offset = the offset relative to the address held by the object for
- derived type arrays.
- base = is the namelist_info of the derived type, when obj is a
- component.
- base_name = the full name for a derived type, including qualifiers
- if any.
- The returned value is a pointer to the object beyond the last one
- accessed, including nested derived types. Notice that the namelist is
- a linear linked list of objects, including derived types and their
- components. A tree, of sorts, is implied by the compound names of
- the derived type components and this is how this function recurses through
- the list. */
-
-/* A generous estimate of the number of characters needed to print
- repeat counts and indices, including commas, asterices and brackets. */
-
-#define NML_DIGITS 20
-
-static void
-namelist_write_newline (st_parameter_dt *dtp)
-{
- if (!is_internal_unit (dtp))
- {
-#ifdef HAVE_CRLF
- write_character (dtp, "\r\n", 1, 2);
-#else
- write_character (dtp, "\n", 1, 1);
-#endif
- return;
- }
-
- if (is_array_io (dtp))
- {
- gfc_offset record;
- int finished;
- char *p;
- int length = dtp->u.p.current_unit->bytes_left;
-
- p = write_block (dtp, length);
- if (p == NULL)
- return;
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, ' ', length);
- }
- else
- memset (p, ' ', length);
-
- /* Now that the current record has been padded out,
- determine where the next record in the array is. */
- record = next_array_record (dtp, dtp->u.p.current_unit->ls,
- &finished);
- if (finished)
- dtp->u.p.current_unit->endfile = AT_ENDFILE;
- else
- {
- /* Now seek to this record */
- record = record * dtp->u.p.current_unit->recl;
-
- if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
- {
- generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
- return;
- }
-
- dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
- }
- }
- else
- write_character (dtp, " ", 1, 1);
-}
-
-
-static namelist_info *
-nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
- namelist_info * base, char * base_name)
-{
- int rep_ctr;
- int num;
- int nml_carry;
- int len;
- index_type obj_size;
- index_type nelem;
- size_t dim_i;
- size_t clen;
- index_type elem_ctr;
- size_t obj_name_len;
- void * p ;
- char cup;
- char * obj_name;
- char * ext_name;
- size_t ext_name_len;
- char rep_buff[NML_DIGITS];
- namelist_info * cmp;
- namelist_info * retval = obj->next;
- size_t base_name_len;
- size_t base_var_name_len;
- size_t tot_len;
- unit_delim tmp_delim;
-
- /* Set the character to be used to separate values
- to a comma or semi-colon. */
-
- char semi_comma =
- dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';';
-
- /* Write namelist variable names in upper case. If a derived type,
- nothing is output. If a component, base and base_name are set. */
-
- if (obj->type != BT_DERIVED)
- {
- namelist_write_newline (dtp);
- write_character (dtp, " ", 1, 1);
-
- len = 0;
- if (base)
- {
- len = strlen (base->var_name);
- base_name_len = strlen (base_name);
- for (dim_i = 0; dim_i < base_name_len; dim_i++)
- {
- cup = toupper ((int) base_name[dim_i]);
- write_character (dtp, &cup, 1, 1);
- }
- }
- clen = strlen (obj->var_name);
- for (dim_i = len; dim_i < clen; dim_i++)
- {
- cup = toupper ((int) obj->var_name[dim_i]);
- write_character (dtp, &cup, 1, 1);
- }
- write_character (dtp, "=", 1, 1);
- }
-
- /* Counts the number of data output on a line, including names. */
-
- num = 1;
-
- len = obj->len;
-
- switch (obj->type)
- {
-
- case BT_REAL:
- obj_size = size_from_real_kind (len);
- break;
-
- case BT_COMPLEX:
- obj_size = size_from_complex_kind (len);
- break;
-
- case BT_CHARACTER:
- obj_size = obj->string_length;
- break;
-
- default:
- obj_size = len;
- }
-
- if (obj->var_rank)
- obj_size = obj->size;
-
- /* Set the index vector and count the number of elements. */
-
- nelem = 1;
- for (dim_i = 0; dim_i < (size_t) obj->var_rank; dim_i++)
- {
- obj->ls[dim_i].idx = GFC_DESCRIPTOR_LBOUND(obj, dim_i);
- nelem = nelem * GFC_DESCRIPTOR_EXTENT (obj, dim_i);
- }
-
- /* Main loop to output the data held in the object. */
-
- rep_ctr = 1;
- for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
- {
-
- /* Build the pointer to the data value. The offset is passed by
- recursive calls to this function for arrays of derived types.
- Is NULL otherwise. */
-
- p = (void *)(obj->mem_pos + elem_ctr * obj_size);
- p += offset;
-
- /* Check for repeat counts of intrinsic types. */
-
- if ((elem_ctr < (nelem - 1)) &&
- (obj->type != BT_DERIVED) &&
- !memcmp (p, (void*)(p + obj_size ), obj_size ))
- {
- rep_ctr++;
- }
-
- /* Execute a repeated output. Note the flag no_leading_blank that
- is used in the functions used to output the intrinsic types. */
-
- else
- {
- if (rep_ctr > 1)
- {
- snprintf(rep_buff, NML_DIGITS, " %d*", rep_ctr);
- write_character (dtp, rep_buff, 1, strlen (rep_buff));
- dtp->u.p.no_leading_blank = 1;
- }
- num++;
-
- /* Output the data, if an intrinsic type, or recurse into this
- routine to treat derived types. */
-
- switch (obj->type)
- {
-
- case BT_INTEGER:
- write_integer (dtp, p, len);
- break;
-
- case BT_LOGICAL:
- write_logical (dtp, p, len);
- break;
-
- case BT_CHARACTER:
- tmp_delim = dtp->u.p.current_unit->delim_status;
- if (dtp->u.p.nml_delim == '"')
- dtp->u.p.current_unit->delim_status = DELIM_QUOTE;
- if (dtp->u.p.nml_delim == '\'')
- dtp->u.p.current_unit->delim_status = DELIM_APOSTROPHE;
- write_character (dtp, p, 1, obj->string_length);
- dtp->u.p.current_unit->delim_status = tmp_delim;
- break;
-
- case BT_REAL:
- write_real (dtp, p, len);
- break;
-
- case BT_COMPLEX:
- dtp->u.p.no_leading_blank = 0;
- num++;
- write_complex (dtp, p, len, obj_size);
- break;
-
- case BT_DERIVED:
-
- /* To treat a derived type, we need to build two strings:
- ext_name = the name, including qualifiers that prepends
- component names in the output - passed to
- nml_write_obj.
- obj_name = the derived type name with no qualifiers but %
- appended. This is used to identify the
- components. */
-
- /* First ext_name => get length of all possible components */
-
- base_name_len = base_name ? strlen (base_name) : 0;
- base_var_name_len = base ? strlen (base->var_name) : 0;
- ext_name_len = base_name_len + base_var_name_len
- + strlen (obj->var_name) + obj->var_rank * NML_DIGITS + 1;
- ext_name = (char*)xmalloc (ext_name_len);
-
- memcpy (ext_name, base_name, base_name_len);
- clen = strlen (obj->var_name + base_var_name_len);
- memcpy (ext_name + base_name_len,
- obj->var_name + base_var_name_len, clen);
-
- /* Append the qualifier. */
-
- tot_len = base_name_len + clen;
- for (dim_i = 0; dim_i < (size_t) obj->var_rank; dim_i++)
- {
- if (!dim_i)
- {
- ext_name[tot_len] = '(';
- tot_len++;
- }
- snprintf (ext_name + tot_len, ext_name_len - tot_len, "%d",
- (int) obj->ls[dim_i].idx);
- tot_len += strlen (ext_name + tot_len);
- ext_name[tot_len] = ((int) dim_i == obj->var_rank - 1) ? ')' : ',';
- tot_len++;
- }
-
- ext_name[tot_len] = '\0';
-
- /* Now obj_name. */
-
- obj_name_len = strlen (obj->var_name) + 1;
- obj_name = xmalloc (obj_name_len+1);
- memcpy (obj_name, obj->var_name, obj_name_len-1);
- memcpy (obj_name + obj_name_len-1, "%", 2);
-
- /* Now loop over the components. Update the component pointer
- with the return value from nml_write_obj => this loop jumps
- past nested derived types. */
-
- for (cmp = obj->next;
- cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
- cmp = retval)
- {
- retval = nml_write_obj (dtp, cmp,
- (index_type)(p - obj->mem_pos),
- obj, ext_name);
- }
-
- free (obj_name);
- free (ext_name);
- goto obj_loop;
-
- default:
- internal_error (&dtp->common, "Bad type for namelist write");
- }
-
- /* Reset the leading blank suppression, write a comma (or semi-colon)
- and, if 5 values have been output, write a newline and advance
- to column 2. Reset the repeat counter. */
-
- dtp->u.p.no_leading_blank = 0;
- write_character (dtp, &semi_comma, 1, 1);
- if (num > 5)
- {
- num = 0;
- namelist_write_newline (dtp);
- write_character (dtp, " ", 1, 1);
- }
- rep_ctr = 1;
- }
-
- /* Cycle through and increment the index vector. */
-
-obj_loop:
-
- nml_carry = 1;
- for (dim_i = 0; nml_carry && (dim_i < (size_t) obj->var_rank); dim_i++)
- {
- obj->ls[dim_i].idx += nml_carry ;
- nml_carry = 0;
- if (obj->ls[dim_i].idx > GFC_DESCRIPTOR_UBOUND(obj,dim_i))
- {
- obj->ls[dim_i].idx = GFC_DESCRIPTOR_LBOUND(obj,dim_i);
- nml_carry = 1;
- }
- }
- }
-
- /* Return a pointer beyond the furthest object accessed. */
-
- return retval;
-}
-
-
-/* This is the entry function for namelist writes. It outputs the name
- of the namelist and iterates through the namelist by calls to
- nml_write_obj. The call below has dummys in the arguments used in
- the treatment of derived types. */
-
-void
-namelist_write (st_parameter_dt *dtp)
-{
- namelist_info * t1, *t2, *dummy = NULL;
- index_type i;
- index_type dummy_offset = 0;
- char c;
- char * dummy_name = NULL;
- unit_delim tmp_delim = DELIM_UNSPECIFIED;
-
- /* Set the delimiter for namelist output. */
- tmp_delim = dtp->u.p.current_unit->delim_status;
-
- dtp->u.p.nml_delim = tmp_delim == DELIM_APOSTROPHE ? '\'' : '"';
-
- /* Temporarily disable namelist delimters. */
- dtp->u.p.current_unit->delim_status = DELIM_NONE;
-
- write_character (dtp, "&", 1, 1);
-
- /* Write namelist name in upper case - f95 std. */
- for (i = 0 ;i < dtp->namelist_name_len ;i++ )
- {
- c = toupper ((int) dtp->namelist_name[i]);
- write_character (dtp, &c, 1 ,1);
- }
-
- if (dtp->u.p.ionml != NULL)
- {
- t1 = dtp->u.p.ionml;
- while (t1 != NULL)
- {
- t2 = t1;
- t1 = nml_write_obj (dtp, t2, dummy_offset, dummy, dummy_name);
- }
- }
-
- namelist_write_newline (dtp);
- write_character (dtp, " /", 1, 2);
- /* Restore the original delimiter. */
- dtp->u.p.current_unit->delim_status = tmp_delim;
-}
-
-#undef NML_DIGITS
diff --git a/gcc-4.8.1/libgfortran/io/write_float.def b/gcc-4.8.1/libgfortran/io/write_float.def
deleted file mode 100644
index 5b76fd596..000000000
--- a/gcc-4.8.1/libgfortran/io/write_float.def
+++ /dev/null
@@ -1,1268 +0,0 @@
-/* Copyright (C) 2007-2013 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- Write float code factoring to this file by Jerry DeLisle
- F2003 I/O support contributed by Jerry DeLisle
-
-This file is part of the GNU Fortran runtime library (libgfortran).
-
-Libgfortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-Libgfortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-
-typedef enum
-{ S_NONE, S_MINUS, S_PLUS }
-sign_t;
-
-/* Given a flag that indicates if a value is negative or not, return a
- sign_t that gives the sign that we need to produce. */
-
-static sign_t
-calculate_sign (st_parameter_dt *dtp, int negative_flag)
-{
- sign_t s = S_NONE;
-
- if (negative_flag)
- s = S_MINUS;
- else
- switch (dtp->u.p.sign_status)
- {
- case SIGN_SP: /* Show sign. */
- s = S_PLUS;
- break;
- case SIGN_SS: /* Suppress sign. */
- s = S_NONE;
- break;
- case SIGN_S: /* Processor defined. */
- case SIGN_UNSPECIFIED:
- s = options.optional_plus ? S_PLUS : S_NONE;
- break;
- }
-
- return s;
-}
-
-
-/* Determine the precision except for EN format. For G format,
- determines an upper bound to be used for sizing the buffer. */
-
-static int
-determine_precision (st_parameter_dt * dtp, const fnode * f, int len)
-{
- int precision = f->u.real.d;
-
- switch (f->format)
- {
- case FMT_F:
- case FMT_G:
- precision += dtp->u.p.scale_factor;
- break;
- case FMT_ES:
- /* Scale factor has no effect on output. */
- break;
- case FMT_E:
- case FMT_D:
- /* See F2008 10.7.2.3.3.6 */
- if (dtp->u.p.scale_factor <= 0)
- precision += dtp->u.p.scale_factor - 1;
- break;
- default:
- return -1;
- }
-
- /* If the scale factor has a large negative value, we must do our
- own rounding? Use ROUND='NEAREST', which should be what snprintf
- is using as well. */
- if (precision < 0 &&
- (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED
- || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED))
- dtp->u.p.current_unit->round_status = ROUND_NEAREST;
-
- /* Add extra guard digits up to at least full precision when we do
- our own rounding. */
- if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED
- && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED)
- {
- precision += 2 * len + 4;
- if (precision < 0)
- precision = 0;
- }
-
- return precision;
-}
-
-
-/* Output a real number according to its format which is FMT_G free. */
-
-static try
-output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
- int nprinted, int precision, int sign_bit, bool zero_flag)
-{
- char *out;
- char *digits;
- int e, w, d, p, i;
- char expchar, rchar;
- format_token ft;
- /* Number of digits before the decimal point. */
- int nbefore;
- /* Number of zeros after the decimal point. */
- int nzero;
- /* Number of digits after the decimal point. */
- int nafter;
- /* Number of zeros after the decimal point, whatever the precision. */
- int nzero_real;
- int leadzero;
- int nblanks;
- int ndigits, edigits;
- sign_t sign;
-
- ft = f->format;
- w = f->u.real.w;
- d = f->u.real.d;
- p = dtp->u.p.scale_factor;
-
- rchar = '5';
- nzero_real = -1;
-
- /* We should always know the field width and precision. */
- if (d < 0)
- internal_error (&dtp->common, "Unspecified precision");
-
- sign = calculate_sign (dtp, sign_bit);
-
- /* Calculate total number of digits. */
- if (ft == FMT_F)
- ndigits = nprinted - 2;
- else
- ndigits = precision + 1;
-
- /* Read the exponent back in. */
- if (ft != FMT_F)
- e = atoi (&buffer[ndigits + 3]) + 1;
- else
- e = 0;
-
- /* Make sure zero comes out as 0.0e0. */
- if (zero_flag)
- e = 0;
-
- /* Normalize the fractional component. */
- if (ft != FMT_F)
- {
- buffer[2] = buffer[1];
- digits = &buffer[2];
- }
- else
- digits = &buffer[1];
-
- /* Figure out where to place the decimal point. */
- switch (ft)
- {
- case FMT_F:
- nbefore = ndigits - precision;
- /* Make sure the decimal point is a '.'; depending on the
- locale, this might not be the case otherwise. */
- digits[nbefore] = '.';
- if (p != 0)
- {
- if (p > 0)
- {
-
- memmove (digits + nbefore, digits + nbefore + 1, p);
- digits[nbefore + p] = '.';
- nbefore += p;
- nafter = d - p;
- if (nafter < 0)
- nafter = 0;
- nafter = d;
- nzero = nzero_real = 0;
- }
- else /* p < 0 */
- {
- if (nbefore + p >= 0)
- {
- nzero = 0;
- memmove (digits + nbefore + p + 1, digits + nbefore + p, -p);
- nbefore += p;
- digits[nbefore] = '.';
- nafter = d;
- }
- else
- {
- nzero = -(nbefore + p);
- memmove (digits + 1, digits, nbefore);
- digits++;
- nafter = d + nbefore;
- nbefore = 0;
- }
- nzero_real = nzero;
- if (nzero > d)
- nzero = d;
- }
- }
- else
- {
- nzero = nzero_real = 0;
- nafter = d;
- }
-
- while (digits[0] == '0' && nbefore > 0)
- {
- digits++;
- nbefore--;
- ndigits--;
- }
-
- expchar = 0;
- /* If we need to do rounding ourselves, get rid of the dot by
- moving the fractional part. */
- if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED
- && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED)
- memmove (digits + nbefore, digits + nbefore + 1, ndigits - nbefore);
- break;
-
- case FMT_E:
- case FMT_D:
- i = dtp->u.p.scale_factor;
- if (d <= 0 && p == 0)
- {
- generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not "
- "greater than zero in format specifier 'E' or 'D'");
- return FAILURE;
- }
- if (p <= -d || p >= d + 2)
- {
- generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor "
- "out of range in format specifier 'E' or 'D'");
- return FAILURE;
- }
-
- if (!zero_flag)
- e -= p;
- if (p < 0)
- {
- nbefore = 0;
- nzero = -p;
- nafter = d + p;
- }
- else if (p > 0)
- {
- nbefore = p;
- nzero = 0;
- nafter = (d - p) + 1;
- }
- else /* p == 0 */
- {
- nbefore = 0;
- nzero = 0;
- nafter = d;
- }
-
- if (ft == FMT_E)
- expchar = 'E';
- else
- expchar = 'D';
- break;
-
- case FMT_EN:
- /* The exponent must be a multiple of three, with 1-3 digits before
- the decimal point. */
- if (!zero_flag)
- e--;
- if (e >= 0)
- nbefore = e % 3;
- else
- {
- nbefore = (-e) % 3;
- if (nbefore != 0)
- nbefore = 3 - nbefore;
- }
- e -= nbefore;
- nbefore++;
- nzero = 0;
- nafter = d;
- expchar = 'E';
- break;
-
- case FMT_ES:
- if (!zero_flag)
- e--;
- nbefore = 1;
- nzero = 0;
- nafter = d;
- expchar = 'E';
- break;
-
- default:
- /* Should never happen. */
- internal_error (&dtp->common, "Unexpected format token");
- }
-
- if (zero_flag)
- goto skip;
-
- /* Round the value. The value being rounded is an unsigned magnitude. */
- switch (dtp->u.p.current_unit->round_status)
- {
- /* For processor defined and unspecified rounding we use
- snprintf to print the exact number of digits needed, and thus
- let snprintf handle the rounding. On system claiming support
- for IEEE 754, this ought to be round to nearest, ties to
- even, corresponding to the Fortran ROUND='NEAREST'. */
- case ROUND_PROCDEFINED:
- case ROUND_UNSPECIFIED:
- case ROUND_ZERO: /* Do nothing and truncation occurs. */
- goto skip;
- case ROUND_UP:
- if (sign_bit)
- goto skip;
- goto updown;
- case ROUND_DOWN:
- if (!sign_bit)
- goto skip;
- goto updown;
- case ROUND_NEAREST:
- /* Round compatible unless there is a tie. A tie is a 5 with
- all trailing zero's. */
- i = nafter + nbefore;
- if (digits[i] == '5')
- {
- for(i++ ; i < ndigits; i++)
- {
- if (digits[i] != '0')
- goto do_rnd;
- }
- /* It is a tie so round to even. */
- switch (digits[nafter + nbefore - 1])
- {
- case '1':
- case '3':
- case '5':
- case '7':
- case '9':
- /* If odd, round away from zero to even. */
- break;
- default:
- /* If even, skip rounding, truncate to even. */
- goto skip;
- }
- }
- /* Fall through. */
- /* The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
- case ROUND_COMPATIBLE:
- rchar = '5';
- goto do_rnd;
- }
-
- updown:
-
- rchar = '0';
- if (w > 0 && d == 0 && p == 0)
- nbefore = 1;
- /* Scan for trailing zeros to see if we really need to round it. */
- for(i = nbefore + nafter; i < ndigits; i++)
- {
- if (digits[i] != '0')
- goto do_rnd;
- }
- goto skip;
-
- do_rnd:
-
- if (nbefore + nafter == 0)
- {
- ndigits = 0;
- if (nzero_real == d && digits[0] >= rchar)
- {
- /* We rounded to zero but shouldn't have */
- nzero--;
- nafter = 1;
- digits[0] = '1';
- ndigits = 1;
- }
- }
- else if (nbefore + nafter < ndigits)
- {
- i = ndigits = nbefore + nafter;
- if (digits[i] >= rchar)
- {
- /* Propagate the carry. */
- for (i--; i >= 0; i--)
- {
- if (digits[i] != '9')
- {
- digits[i]++;
- break;
- }
- digits[i] = '0';
- }
-
- if (i < 0)
- {
- /* The carry overflowed. Fortunately we have some spare
- space at the start of the buffer. We may discard some
- digits, but this is ok because we already know they are
- zero. */
- digits--;
- digits[0] = '1';
- if (ft == FMT_F)
- {
- if (nzero > 0)
- {
- nzero--;
- nafter++;
- }
- else
- nbefore++;
- }
- else if (ft == FMT_EN)
- {
- nbefore++;
- if (nbefore == 4)
- {
- nbefore = 1;
- e += 3;
- }
- }
- else
- e++;
- }
- }
- }
-
- skip:
-
- /* Calculate the format of the exponent field. */
- if (expchar)
- {
- edigits = 1;
- for (i = abs (e); i >= 10; i /= 10)
- edigits++;
-
- if (f->u.real.e < 0)
- {
- /* Width not specified. Must be no more than 3 digits. */
- if (e > 999 || e < -999)
- edigits = -1;
- else
- {
- edigits = 4;
- if (e > 99 || e < -99)
- expchar = ' ';
- }
- }
- else
- {
- /* Exponent width specified, check it is wide enough. */
- if (edigits > f->u.real.e)
- edigits = -1;
- else
- edigits = f->u.real.e + 2;
- }
- }
- else
- edigits = 0;
-
- /* Scan the digits string and count the number of zeros. If we make it
- all the way through the loop, we know the value is zero after the
- rounding completed above. */
- int hasdot = 0;
- for (i = 0; i < ndigits + hasdot; i++)
- {
- if (digits[i] == '.')
- hasdot = 1;
- else if (digits[i] != '0')
- break;
- }
-
- /* To format properly, we need to know if the rounded result is zero and if
- so, we set the zero_flag which may have been already set for
- actual zero. */
- if (i == ndigits + hasdot)
- {
- zero_flag = true;
- /* The output is zero, so set the sign according to the sign bit unless
- -fno-sign-zero was specified. */
- if (compile_options.sign_zero == 1)
- sign = calculate_sign (dtp, sign_bit);
- else
- sign = calculate_sign (dtp, 0);
- }
-
- /* Pick a field size if none was specified, taking into account small
- values that may have been rounded to zero. */
- if (w <= 0)
- {
- if (zero_flag)
- w = d + (sign != S_NONE ? 2 : 1) + (d == 0 ? 1 : 0);
- else
- {
- w = nbefore + nzero + nafter + (sign != S_NONE ? 2 : 1);
- w = w == 1 ? 2 : w;
- }
- }
-
- /* Work out how much padding is needed. */
- nblanks = w - (nbefore + nzero + nafter + edigits + 1);
- if (sign != S_NONE)
- nblanks--;
-
- if (dtp->u.p.g0_no_blanks)
- {
- w -= nblanks;
- nblanks = 0;
- }
-
- /* Create the ouput buffer. */
- out = write_block (dtp, w);
- if (out == NULL)
- return FAILURE;
-
- /* Check the value fits in the specified field width. */
- if (nblanks < 0 || edigits == -1 || w == 1 || (w == 2 && sign != S_NONE))
- {
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *out4 = (gfc_char4_t *) out;
- memset4 (out4, '*', w);
- return FAILURE;
- }
- star_fill (out, w);
- return FAILURE;
- }
-
- /* See if we have space for a zero before the decimal point. */
- if (nbefore == 0 && nblanks > 0)
- {
- leadzero = 1;
- nblanks--;
- }
- else
- leadzero = 0;
-
- /* For internal character(kind=4) units, we duplicate the code used for
- regular output slightly modified. This needs to be maintained
- consistent with the regular code that follows this block. */
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *out4 = (gfc_char4_t *) out;
- /* Pad to full field width. */
-
- if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
- {
- memset4 (out4, ' ', nblanks);
- out4 += nblanks;
- }
-
- /* Output the initial sign (if any). */
- if (sign == S_PLUS)
- *(out4++) = '+';
- else if (sign == S_MINUS)
- *(out4++) = '-';
-
- /* Output an optional leading zero. */
- if (leadzero)
- *(out4++) = '0';
-
- /* Output the part before the decimal point, padding with zeros. */
- if (nbefore > 0)
- {
- if (nbefore > ndigits)
- {
- i = ndigits;
- memcpy4 (out4, digits, i);
- ndigits = 0;
- while (i < nbefore)
- out4[i++] = '0';
- }
- else
- {
- i = nbefore;
- memcpy4 (out4, digits, i);
- ndigits -= i;
- }
-
- digits += i;
- out4 += nbefore;
- }
-
- /* Output the decimal point. */
- *(out4++) = dtp->u.p.current_unit->decimal_status
- == DECIMAL_POINT ? '.' : ',';
- if (ft == FMT_F
- && (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED
- || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED))
- digits++;
-
- /* Output leading zeros after the decimal point. */
- if (nzero > 0)
- {
- for (i = 0; i < nzero; i++)
- *(out4++) = '0';
- }
-
- /* Output digits after the decimal point, padding with zeros. */
- if (nafter > 0)
- {
- if (nafter > ndigits)
- i = ndigits;
- else
- i = nafter;
-
- memcpy4 (out4, digits, i);
- while (i < nafter)
- out4[i++] = '0';
-
- digits += i;
- ndigits -= i;
- out4 += nafter;
- }
-
- /* Output the exponent. */
- if (expchar)
- {
- if (expchar != ' ')
- {
- *(out4++) = expchar;
- edigits--;
- }
- snprintf (buffer, size, "%+0*d", edigits, e);
- memcpy4 (out4, buffer, edigits);
- }
-
- if (dtp->u.p.no_leading_blank)
- {
- out4 += edigits;
- memset4 (out4, ' ' , nblanks);
- dtp->u.p.no_leading_blank = 0;
- }
- return SUCCESS;
- } /* End of character(kind=4) internal unit code. */
-
- /* Pad to full field width. */
-
- if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
- {
- memset (out, ' ', nblanks);
- out += nblanks;
- }
-
- /* Output the initial sign (if any). */
- if (sign == S_PLUS)
- *(out++) = '+';
- else if (sign == S_MINUS)
- *(out++) = '-';
-
- /* Output an optional leading zero. */
- if (leadzero)
- *(out++) = '0';
-
- /* Output the part before the decimal point, padding with zeros. */
- if (nbefore > 0)
- {
- if (nbefore > ndigits)
- {
- i = ndigits;
- memcpy (out, digits, i);
- ndigits = 0;
- while (i < nbefore)
- out[i++] = '0';
- }
- else
- {
- i = nbefore;
- memcpy (out, digits, i);
- ndigits -= i;
- }
-
- digits += i;
- out += nbefore;
- }
-
- /* Output the decimal point. */
- *(out++) = dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? '.' : ',';
- if (ft == FMT_F
- && (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED
- || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED))
- digits++;
-
- /* Output leading zeros after the decimal point. */
- if (nzero > 0)
- {
- for (i = 0; i < nzero; i++)
- *(out++) = '0';
- }
-
- /* Output digits after the decimal point, padding with zeros. */
- if (nafter > 0)
- {
- if (nafter > ndigits)
- i = ndigits;
- else
- i = nafter;
-
- memcpy (out, digits, i);
- while (i < nafter)
- out[i++] = '0';
-
- digits += i;
- ndigits -= i;
- out += nafter;
- }
-
- /* Output the exponent. */
- if (expchar)
- {
- if (expchar != ' ')
- {
- *(out++) = expchar;
- edigits--;
- }
- snprintf (buffer, size, "%+0*d", edigits, e);
- memcpy (out, buffer, edigits);
- }
-
- if (dtp->u.p.no_leading_blank)
- {
- out += edigits;
- memset( out , ' ' , nblanks );
- dtp->u.p.no_leading_blank = 0;
- }
-
- return SUCCESS;
-}
-
-
-/* Write "Infinite" or "Nan" as appropriate for the given format. */
-
-static void
-write_infnan (st_parameter_dt *dtp, const fnode *f, int isnan_flag, int sign_bit)
-{
- char * p, fin;
- int nb = 0;
- sign_t sign;
- int mark;
-
- if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
- {
- sign = calculate_sign (dtp, sign_bit);
- mark = (sign == S_PLUS || sign == S_MINUS) ? 8 : 7;
-
- nb = f->u.real.w;
-
- /* If the field width is zero, the processor must select a width
- not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
-
- if ((nb == 0) || dtp->u.p.g0_no_blanks)
- {
- if (isnan_flag)
- nb = 3;
- else
- nb = (sign == S_PLUS || sign == S_MINUS) ? 4 : 3;
- }
- p = write_block (dtp, nb);
- if (p == NULL)
- return;
- if (nb < 3)
- {
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, '*', nb);
- }
- else
- memset (p, '*', nb);
- return;
- }
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, ' ', nb);
- }
- else
- memset(p, ' ', nb);
-
- if (!isnan_flag)
- {
- if (sign_bit)
- {
- /* If the sign is negative and the width is 3, there is
- insufficient room to output '-Inf', so output asterisks */
- if (nb == 3)
- {
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memset4 (p4, '*', nb);
- }
- else
- memset (p, '*', nb);
- return;
- }
- /* The negative sign is mandatory */
- fin = '-';
- }
- else
- /* The positive sign is optional, but we output it for
- consistency */
- fin = '+';
-
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
-
- if (nb > mark)
- /* We have room, so output 'Infinity' */
- memcpy4 (p4 + nb - 8, "Infinity", 8);
- else
- /* For the case of width equals mark, there is not enough room
- for the sign and 'Infinity' so we go with 'Inf' */
- memcpy4 (p4 + nb - 3, "Inf", 3);
-
- if (sign == S_PLUS || sign == S_MINUS)
- {
- if (nb < 9 && nb > 3)
- /* Put the sign in front of Inf */
- p4[nb - 4] = (gfc_char4_t) fin;
- else if (nb > 8)
- /* Put the sign in front of Infinity */
- p4[nb - 9] = (gfc_char4_t) fin;
- }
- return;
- }
-
- if (nb > mark)
- /* We have room, so output 'Infinity' */
- memcpy(p + nb - 8, "Infinity", 8);
- else
- /* For the case of width equals 8, there is not enough room
- for the sign and 'Infinity' so we go with 'Inf' */
- memcpy(p + nb - 3, "Inf", 3);
-
- if (sign == S_PLUS || sign == S_MINUS)
- {
- if (nb < 9 && nb > 3)
- p[nb - 4] = fin; /* Put the sign in front of Inf */
- else if (nb > 8)
- p[nb - 9] = fin; /* Put the sign in front of Infinity */
- }
- }
- else
- {
- if (unlikely (is_char4_unit (dtp)))
- {
- gfc_char4_t *p4 = (gfc_char4_t *) p;
- memcpy4 (p4 + nb - 3, "NaN", 3);
- }
- else
- memcpy(p + nb - 3, "NaN", 3);
- }
- return;
- }
-}
-
-
-/* Returns the value of 10**d. */
-
-#define CALCULATE_EXP(x) \
-static GFC_REAL_ ## x \
-calculate_exp_ ## x (int d)\
-{\
- int i;\
- GFC_REAL_ ## x r = 1.0;\
- for (i = 0; i< (d >= 0 ? d : -d); i++)\
- r *= 10;\
- r = (d >= 0) ? r : 1.0 / r;\
- return r;\
-}
-
-CALCULATE_EXP(4)
-
-CALCULATE_EXP(8)
-
-#ifdef HAVE_GFC_REAL_10
-CALCULATE_EXP(10)
-#endif
-
-#ifdef HAVE_GFC_REAL_16
-CALCULATE_EXP(16)
-#endif
-#undef CALCULATE_EXP
-
-
-/* Define a macro to build code for write_float. */
-
- /* Note: Before output_float is called, snprintf is used to print to buffer the
- number in the format +D.DDDDe+ddd.
-
- # The result will always contain a decimal point, even if no
- digits follow it
-
- - The converted value is to be left adjusted on the field boundary
-
- + A sign (+ or -) always be placed before a number
-
- * prec is used as the precision
-
- e format: [-]d.ddde±dd where there is one digit before the
- decimal-point character and the number of digits after it is
- equal to the precision. The exponent always contains at least two
- digits; if the value is zero, the exponent is 00. */
-
-
-#define TOKENPASTE(x, y) TOKENPASTE2(x, y)
-#define TOKENPASTE2(x, y) x ## y
-
-#define DTOA(suff,prec,val) TOKENPASTE(DTOA2,suff)(prec,val)
-
-#define DTOA2(prec,val) \
-snprintf (buffer, size, "%+-#.*e", (prec), (val))
-
-#define DTOA2L(prec,val) \
-snprintf (buffer, size, "%+-#.*Le", (prec), (val))
-
-
-#if defined(GFC_REAL_16_IS_FLOAT128)
-#define DTOA2Q(prec,val) \
-__qmath_(quadmath_snprintf) (buffer, size, "%+-#.*Qe", (prec), (val))
-#endif
-
-#define FDTOA(suff,prec,val) TOKENPASTE(FDTOA2,suff)(prec,val)
-
-/* For F format, we print to the buffer with f format. */
-#define FDTOA2(prec,val) \
-snprintf (buffer, size, "%+-#.*f", (prec), (val))
-
-#define FDTOA2L(prec,val) \
-snprintf (buffer, size, "%+-#.*Lf", (prec), (val))
-
-
-#if defined(GFC_REAL_16_IS_FLOAT128)
-#define FDTOA2Q(prec,val) \
-__qmath_(quadmath_snprintf) (buffer, size, "%+-#.*Qf", \
- (prec), (val))
-#endif
-
-
-/* Generate corresponding I/O format for FMT_G and output.
- The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
- LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
-
- Data Magnitude Equivalent Conversion
- 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
- m = 0 F(w-n).(d-1), n' '
- 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
- 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
- 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
- ................ ..........
- 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
- m >= 10**d-0.5 Ew.d[Ee]
-
- notes: for Gw.d , n' ' means 4 blanks
- for Gw.dEe, n' ' means e+2 blanks
- for rounding modes adjustment, r, See Fortran F2008 10.7.5.2.2
- the asm volatile is required for 32-bit x86 platforms. */
-
-#define OUTPUT_FLOAT_FMT_G(x,y) \
-static void \
-output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
- GFC_REAL_ ## x m, char *buffer, size_t size, \
- int sign_bit, bool zero_flag, int comp_d) \
-{ \
- int e = f->u.real.e;\
- int d = f->u.real.d;\
- int w = f->u.real.w;\
- fnode newf;\
- GFC_REAL_ ## x rexp_d, r = 0.5;\
- int low, high, mid;\
- int ubound, lbound;\
- char *p, pad = ' ';\
- int save_scale_factor, nb = 0;\
- try result;\
- int nprinted, precision;\
-\
- save_scale_factor = dtp->u.p.scale_factor;\
-\
- switch (dtp->u.p.current_unit->round_status)\
- {\
- case ROUND_ZERO:\
- r = sign_bit ? 1.0 : 0.0;\
- break;\
- case ROUND_UP:\
- r = 1.0;\
- break;\
- case ROUND_DOWN:\
- r = 0.0;\
- break;\
- default:\
- break;\
- }\
-\
- rexp_d = calculate_exp_ ## x (-d);\
- if ((m > 0.0 && ((m < 0.1 - 0.1 * r * rexp_d) || (rexp_d * (m + r) >= 1.0)))\
- || ((m == 0.0) && !(compile_options.allow_std\
- & (GFC_STD_F2003 | GFC_STD_F2008))))\
- { \
- newf.format = FMT_E;\
- newf.u.real.w = w;\
- newf.u.real.d = d - comp_d;\
- newf.u.real.e = e;\
- nb = 0;\
- precision = determine_precision (dtp, &newf, x);\
- nprinted = DTOA(y,precision,m); \
- goto finish;\
- }\
-\
- mid = 0;\
- low = 0;\
- high = d + 1;\
- lbound = 0;\
- ubound = d + 1;\
-\
- while (low <= high)\
- { \
- volatile GFC_REAL_ ## x temp;\
- mid = (low + high) / 2;\
-\
- temp = (calculate_exp_ ## x (mid - 1) * (1 - r * rexp_d));\
-\
- if (m < temp)\
- { \
- ubound = mid;\
- if (ubound == lbound + 1)\
- break;\
- high = mid - 1;\
- }\
- else if (m > temp)\
- { \
- lbound = mid;\
- if (ubound == lbound + 1)\
- { \
- mid ++;\
- break;\
- }\
- low = mid + 1;\
- }\
- else\
- {\
- mid++;\
- break;\
- }\
- }\
-\
- nb = e <= 0 ? 4 : e + 2;\
- nb = nb >= w ? w - 1 : nb;\
- newf.format = FMT_F;\
- newf.u.real.w = w - nb;\
- newf.u.real.d = m == 0.0 ? d - 1 : -(mid - d - 1) ;\
- dtp->u.p.scale_factor = 0;\
- precision = determine_precision (dtp, &newf, x); \
- nprinted = FDTOA(y,precision,m); \
-\
- finish:\
- result = output_float (dtp, &newf, buffer, size, nprinted, precision,\
- sign_bit, zero_flag);\
- dtp->u.p.scale_factor = save_scale_factor;\
-\
-\
- if (nb > 0 && !dtp->u.p.g0_no_blanks)\
- {\
- p = write_block (dtp, nb);\
- if (p == NULL)\
- return;\
- if (result == FAILURE)\
- pad = '*';\
- if (unlikely (is_char4_unit (dtp)))\
- {\
- gfc_char4_t *p4 = (gfc_char4_t *) p;\
- memset4 (p4, pad, nb);\
- }\
- else \
- memset (p, pad, nb);\
- }\
-}\
-
-OUTPUT_FLOAT_FMT_G(4,)
-
-OUTPUT_FLOAT_FMT_G(8,)
-
-#ifdef HAVE_GFC_REAL_10
-OUTPUT_FLOAT_FMT_G(10,L)
-#endif
-
-#ifdef HAVE_GFC_REAL_16
-# ifdef GFC_REAL_16_IS_FLOAT128
-OUTPUT_FLOAT_FMT_G(16,Q)
-#else
-OUTPUT_FLOAT_FMT_G(16,L)
-#endif
-#endif
-
-#undef OUTPUT_FLOAT_FMT_G
-
-
-/* EN format is tricky since the number of significant digits depends
- on the magnitude. Solve it by first printing a temporary value and
- figure out the number of significant digits from the printed
- exponent. */
-
-#define EN_PREC(x,y)\
-{\
- GFC_REAL_ ## x tmp; \
- tmp = * (GFC_REAL_ ## x *)source; \
- if (isfinite (tmp)) \
- nprinted = DTOA(y,0,tmp); \
- else\
- nprinted = -1;\
-}\
-
-static int
-determine_en_precision (st_parameter_dt *dtp, const fnode *f,
- const char *source, int len)
-{
- int nprinted;
- char buffer[10];
- const size_t size = 10;
-
- switch (len)
- {
- case 4:
- EN_PREC(4,)
- break;
-
- case 8:
- EN_PREC(8,)
- break;
-
-#ifdef HAVE_GFC_REAL_10
- case 10:
- EN_PREC(10,L)
- break;
-#endif
-#ifdef HAVE_GFC_REAL_16
- case 16:
-# ifdef GFC_REAL_16_IS_FLOAT128
- EN_PREC(16,Q)
-# else
- EN_PREC(16,L)
-# endif
- break;
-#endif
- default:
- internal_error (NULL, "bad real kind");
- }
-
- if (nprinted == -1)
- return -1;
-
- int e = atoi (&buffer[5]);
- int nbefore; /* digits before decimal point - 1. */
- if (e >= 0)
- nbefore = e % 3;
- else
- {
- nbefore = (-e) % 3;
- if (nbefore != 0)
- nbefore = 3 - nbefore;
- }
- int prec = f->u.real.d + nbefore;
- if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED
- && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED)
- prec += 2 * len + 4;
- return prec;
-}
-
-
-#define WRITE_FLOAT(x,y)\
-{\
- GFC_REAL_ ## x tmp;\
- tmp = * (GFC_REAL_ ## x *)source;\
- sign_bit = signbit (tmp);\
- if (!isfinite (tmp))\
- { \
- write_infnan (dtp, f, isnan (tmp), sign_bit);\
- return;\
- }\
- tmp = sign_bit ? -tmp : tmp;\
- zero_flag = (tmp == 0.0);\
- if (f->format == FMT_G)\
- output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
- zero_flag, comp_d);\
- else\
- {\
- if (f->format == FMT_F)\
- nprinted = FDTOA(y,precision,tmp); \
- else\
- nprinted = DTOA(y,precision,tmp); \
- output_float (dtp, f, buffer, size, nprinted, precision,\
- sign_bit, zero_flag);\
- }\
-}\
-
-/* Output a real number according to its format. */
-
-static void
-write_float (st_parameter_dt *dtp, const fnode *f, const char *source, \
- int len, int comp_d)
-{
- int sign_bit, nprinted;
- int precision; /* Precision for snprintf call. */
- bool zero_flag;
-
- if (f->format != FMT_EN)
- precision = determine_precision (dtp, f, len);
- else
- precision = determine_en_precision (dtp, f, source, len);
-
- /* 4932 is the maximum exponent of long double and quad precision, 3
- extra characters for the sign, the decimal point, and the
- trailing null, and finally some extra digits depending on the
- requested precision. */
- const size_t size = 4932 + 3 + precision;
- char buffer[size];
-
- switch (len)
- {
- case 4:
- WRITE_FLOAT(4,)
- break;
-
- case 8:
- WRITE_FLOAT(8,)
- break;
-
-#ifdef HAVE_GFC_REAL_10
- case 10:
- WRITE_FLOAT(10,L)
- break;
-#endif
-#ifdef HAVE_GFC_REAL_16
- case 16:
-# ifdef GFC_REAL_16_IS_FLOAT128
- WRITE_FLOAT(16,Q)
-# else
- WRITE_FLOAT(16,L)
-# endif
- break;
-#endif
- default:
- internal_error (NULL, "bad real kind");
- }
-}