Daily bump.
[official-gcc.git] / libgfortran / io / fbuf.c
blob0c6ae546518b125282010233521c7a06cb08823a
1 /* Copyright (C) 2008-2014 Free Software Foundation, Inc.
2 Contributed by Janne Blomqvist
4 This file is part of the GNU Fortran runtime library (libgfortran).
6 Libgfortran is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 Libgfortran is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
26 #include "io.h"
27 #include "fbuf.h"
28 #include "unix.h"
29 #include <string.h>
30 #include <stdlib.h>
33 //#define FBUF_DEBUG
36 void
37 fbuf_init (gfc_unit * u, int len)
39 if (len == 0)
40 len = 512; /* Default size. */
42 u->fbuf = xmalloc (sizeof (struct fbuf));
43 u->fbuf->buf = xmalloc (len);
44 u->fbuf->len = len;
45 u->fbuf->act = u->fbuf->pos = 0;
49 void
50 fbuf_destroy (gfc_unit * u)
52 if (u->fbuf == NULL)
53 return;
54 free (u->fbuf->buf);
55 free (u->fbuf);
56 u->fbuf = NULL;
60 static void
61 #ifdef FBUF_DEBUG
62 fbuf_debug (gfc_unit * u, const char * format, ...)
64 va_list args;
65 va_start(args, format);
66 vfprintf(stderr, format, args);
67 va_end(args);
68 fprintf (stderr, "fbuf_debug pos: %d, act: %d, buf: ''",
69 u->fbuf->pos, u->fbuf->act);
70 for (int ii = 0; ii < u->fbuf->act; ii++)
72 putc (u->fbuf->buf[ii], stderr);
74 fprintf (stderr, "''\n");
76 #else
77 fbuf_debug (gfc_unit * u __attribute__ ((unused)),
78 const char * format __attribute__ ((unused)),
79 ...) {}
80 #endif
84 /* You should probably call this before doing a physical seek on the
85 underlying device. Returns how much the physical position was
86 modified. */
88 int
89 fbuf_reset (gfc_unit * u)
91 int seekval = 0;
93 if (!u->fbuf)
94 return 0;
96 fbuf_debug (u, "fbuf_reset: ");
97 fbuf_flush (u, u->mode);
98 /* If we read past the current position, seek the underlying device
99 back. */
100 if (u->mode == READING && u->fbuf->act > u->fbuf->pos)
102 seekval = - (u->fbuf->act - u->fbuf->pos);
103 fbuf_debug (u, "fbuf_reset seekval %d, ", seekval);
105 u->fbuf->act = u->fbuf->pos = 0;
106 return seekval;
110 /* Return a pointer to the current position in the buffer, and increase
111 the pointer by len. Makes sure that the buffer is big enough,
112 reallocating if necessary. */
114 char *
115 fbuf_alloc (gfc_unit * u, int len)
117 int newlen;
118 char *dest;
119 fbuf_debug (u, "fbuf_alloc len %d, ", len);
120 if (u->fbuf->pos + len > u->fbuf->len)
122 /* Round up to nearest multiple of the current buffer length. */
123 newlen = ((u->fbuf->pos + len) / u->fbuf->len + 1) * u->fbuf->len;
124 dest = realloc (u->fbuf->buf, newlen);
125 if (dest == NULL)
126 return NULL;
127 u->fbuf->buf = dest;
128 u->fbuf->len = newlen;
131 dest = u->fbuf->buf + u->fbuf->pos;
132 u->fbuf->pos += len;
133 if (u->fbuf->pos > u->fbuf->act)
134 u->fbuf->act = u->fbuf->pos;
135 return dest;
139 /* mode argument is WRITING for write mode and READING for read
140 mode. Return value is 0 for success, -1 on failure. */
143 fbuf_flush (gfc_unit * u, unit_mode mode)
145 int nwritten;
147 if (!u->fbuf)
148 return 0;
150 fbuf_debug (u, "fbuf_flush with mode %d: ", mode);
152 if (mode == WRITING)
154 if (u->fbuf->pos > 0)
156 nwritten = swrite (u->s, u->fbuf->buf, u->fbuf->pos);
157 if (nwritten < 0)
158 return -1;
161 /* Salvage remaining bytes for both reading and writing. This
162 happens with the combination of advance='no' and T edit
163 descriptors leaving the final position somewhere not at the end
164 of the record. For reading, this also happens if we sread() past
165 the record boundary. */
166 if (u->fbuf->act > u->fbuf->pos && u->fbuf->pos > 0)
167 memmove (u->fbuf->buf, u->fbuf->buf + u->fbuf->pos,
168 u->fbuf->act - u->fbuf->pos);
170 u->fbuf->act -= u->fbuf->pos;
171 u->fbuf->pos = 0;
173 return 0;
177 /* The mode argument is LIST_WRITING for write mode and LIST_READING for
178 read. This should only be used for list directed I/O.
179 Return value is 0 for success, -1 on failure. */
182 fbuf_flush_list (gfc_unit * u, unit_mode mode)
184 int nwritten;
186 if (!u->fbuf)
187 return 0;
189 if (u->fbuf->pos < 524288) /* Upper limit for list writing. */
190 return 0;
192 fbuf_debug (u, "fbuf_flush_list with mode %d: ", mode);
194 if (mode == LIST_WRITING)
196 nwritten = swrite (u->s, u->fbuf->buf, u->fbuf->pos);
197 if (nwritten < 0)
198 return -1;
201 /* Salvage remaining bytes for both reading and writing. */
202 if (u->fbuf->act > u->fbuf->pos)
203 memmove (u->fbuf->buf, u->fbuf->buf + u->fbuf->pos,
204 u->fbuf->act - u->fbuf->pos);
206 u->fbuf->act -= u->fbuf->pos;
207 u->fbuf->pos = 0;
209 return 0;
214 fbuf_seek (gfc_unit * u, int off, int whence)
216 if (!u->fbuf)
217 return -1;
219 switch (whence)
221 case SEEK_SET:
222 break;
223 case SEEK_CUR:
224 off += u->fbuf->pos;
225 break;
226 case SEEK_END:
227 off += u->fbuf->act;
228 break;
229 default:
230 return -1;
233 fbuf_debug (u, "fbuf_seek, off %d ", off);
234 /* The start of the buffer is always equal to the left tab
235 limit. Moving to the left past the buffer is illegal in C and
236 would also imply moving past the left tab limit, which is never
237 allowed in Fortran. Similarly, seeking past the end of the buffer
238 is not possible, in that case the user must make sure to allocate
239 space with fbuf_alloc(). So return error if that is
240 attempted. */
241 if (off < 0 || off > u->fbuf->act)
242 return -1;
243 u->fbuf->pos = off;
244 return off;
248 /* Fill the buffer with bytes for reading. Returns a pointer to start
249 reading from. If we hit EOF, returns a short read count. If any
250 other error occurs, return NULL. After reading, the caller is
251 expected to call fbuf_seek to update the position with the number
252 of bytes actually processed. */
254 char *
255 fbuf_read (gfc_unit * u, int * len)
257 char *ptr;
258 int oldact, oldpos;
259 int readlen = 0;
261 fbuf_debug (u, "fbuf_read, len %d: ", *len);
262 oldact = u->fbuf->act;
263 oldpos = u->fbuf->pos;
264 ptr = fbuf_alloc (u, *len);
265 u->fbuf->pos = oldpos;
266 if (oldpos + *len > oldact)
268 fbuf_debug (u, "reading %d bytes starting at %d ",
269 oldpos + *len - oldact, oldact);
270 readlen = sread (u->s, u->fbuf->buf + oldact, oldpos + *len - oldact);
271 if (readlen < 0)
272 return NULL;
273 *len = oldact - oldpos + readlen;
275 u->fbuf->act = oldact + readlen;
276 fbuf_debug (u, "fbuf_read done: ");
277 return ptr;
281 /* When the fbuf_getc() inline function runs out of buffer space, it
282 calls this function to fill the buffer with bytes for
283 reading. Never call this function directly. */
286 fbuf_getc_refill (gfc_unit * u)
288 int nread;
289 char *p;
291 fbuf_debug (u, "fbuf_getc_refill ");
293 /* Read 80 bytes (average line length?). This is a compromise
294 between not needing to call the read() syscall all the time and
295 not having to memmove unnecessary stuff when switching to the
296 next record. */
297 nread = 80;
299 p = fbuf_read (u, &nread);
301 if (p && nread > 0)
302 return (unsigned char) u->fbuf->buf[u->fbuf->pos++];
303 else
304 return EOF;