diff options
Diffstat (limited to 'libgfortran/io/unix.c')
-rw-r--r-- | libgfortran/io/unix.c | 137 |
1 files changed, 135 insertions, 2 deletions
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c index 3419d72d75a..aa1dd1fdf59 100644 --- a/libgfortran/io/unix.c +++ b/libgfortran/io/unix.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005 +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Contributed by Andy Vaught @@ -36,6 +36,7 @@ Boston, MA 02110-1301, USA. */ #include <unistd.h> #include <stdio.h> +#include <stdarg.h> #include <sys/stat.h> #include <fcntl.h> #include <assert.h> @@ -45,7 +46,6 @@ Boston, MA 02110-1301, USA. */ #include "libgfortran.h" #include "io.h" -#include "unix.h" #ifndef SSIZE_MAX #define SSIZE_MAX SHRT_MAX @@ -81,6 +81,42 @@ Boston, MA 02110-1301, USA. */ #define S_IWOTH 0 #endif + +/* Unix stream I/O module */ + +#define BUFFER_SIZE 8192 + +typedef struct +{ + stream st; + + int fd; + 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 dirty_offset; /* Start of modified bytes in buffer */ + gfc_offset file_length; /* Length of the file, -1 if not seekable. */ + + char *buffer; + int len; /* Physical length of the current buffer */ + int active; /* Length of valid bytes in the buffer */ + + int prot; + int ndirty; /* Dirty bytes starting at dirty_offset */ + + int special_file; /* =1 if the fd refers to a special file */ + + unsigned unbuffered:1; + + char small_buffer[BUFFER_SIZE]; + +} +unix_stream; + +extern stream *init_error_stream (unix_stream *); +internal_proto(init_error_stream); + + /* This implementation of stream I/O is based on the paper: * * "Exploiting the advantages of mapped files for stream I/O", @@ -1346,6 +1382,103 @@ init_error_stream (unix_stream *error) return (stream *) error; } +/* st_printf()-- simple printf() function for streams that handles the + * formats %d, %s and %c. This function handles printing of error + * messages that originate within the library itself, not from a user + * program. */ + +int +st_printf (const char *format, ...) +{ + int count, total; + va_list arg; + char *p; + const char *q; + stream *s; + char itoa_buf[GFC_ITOA_BUF_SIZE]; + unix_stream err_stream; + + total = 0; + s = init_error_stream (&err_stream); + va_start (arg, format); + + for (;;) + { + count = 0; + + while (format[count] != '%' && format[count] != '\0') + count++; + + if (count != 0) + { + p = salloc_w (s, &count); + memmove (p, format, count); + sfree (s); + } + + total += count; + format += count; + if (*format++ == '\0') + break; + + switch (*format) + { + case 'c': + count = 1; + + p = salloc_w (s, &count); + *p = (char) va_arg (arg, int); + + sfree (s); + break; + + case 'd': + q = gfc_itoa (va_arg (arg, int), itoa_buf, sizeof (itoa_buf)); + count = strlen (q); + + p = salloc_w (s, &count); + memmove (p, q, count); + sfree (s); + break; + + case 'x': + q = xtoa (va_arg (arg, unsigned), itoa_buf, sizeof (itoa_buf)); + count = strlen (q); + + p = salloc_w (s, &count); + memmove (p, q, count); + sfree (s); + break; + + case 's': + q = va_arg (arg, char *); + count = strlen (q); + + p = salloc_w (s, &count); + memmove (p, q, count); + sfree (s); + break; + + case '\0': + return total; + + default: + count = 2; + p = salloc_w (s, &count); + p[0] = format[-1]; + p[1] = format[0]; + sfree (s); + break; + } + + total += count; + format++; + } + + va_end (arg); + return total; +} + /* 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 |