aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io/unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgfortran/io/unix.c')
-rw-r--r--libgfortran/io/unix.c140
1 files changed, 29 insertions, 111 deletions
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index 87d001e..e9ad164 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -142,10 +142,6 @@ typedef struct
}
int_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",
@@ -1155,7 +1151,7 @@ tempfile (st_parameter_open *opp)
template = get_mem (strlen (tempdir) + 20);
- st_sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
+ sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
#ifdef HAVE_MKSTEMP
@@ -1385,122 +1381,44 @@ error_stream (void)
return fd_to_stream (STDERR_FILENO, PROT_WRITE);
}
-/* init_error_stream()-- Return a pointer to the error stream. This
- * subroutine is called when the stream is needed, rather than at
- * initialization. We want to work even if memory has been seriously
- * corrupted. */
-stream *
-init_error_stream (unix_stream *error)
-{
- memset (error, '\0', sizeof (*error));
+/* st_vprintf()-- vprintf function for error output. To avoid buffer
+ overruns, we limit the length of the buffer to ST_VPRINTF_SIZE. 2k
+ is big enough to completely fill a 80x25 terminal, so it shuld be
+ OK. We use a direct write() because it is simpler and least likely
+ to be clobbered by memory corruption. */
- error->fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
+#define ST_VPRINTF_SIZE 2048
- error->st.alloc_w_at = (void *) fd_alloc_w_at;
- error->st.sfree = (void *) fd_sfree;
-
- error->unbuffered = 1;
- error->buffer = error->small_buffer;
+int
+st_vprintf (const char *format, va_list ap)
+{
+ static char buffer[ST_VPRINTF_SIZE];
+ int written;
+ int fd;
- return (stream *) error;
+ fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
+#ifdef HAVE_VSNPRINTF
+ written = vsnprintf(buffer, ST_VPRINTF_SIZE, format, ap);
+#else
+ written = __builtin_vsnprintf(buffer, ST_VPRINTF_SIZE, format, ap);
+#endif
+ written = write (fd, buffer, written);
+ return written;
}
-/* 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. */
+/* st_printf()-- printf() function for error output. This just calls
+ st_vprintf() to do the actual work. */
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;
+ int written;
+ va_list ap;
+ va_start (ap, format);
+ written = st_vprintf(format, ap);
+ va_end (ap);
+ return written;
}