* config/sh/linux-atomic.asm (ATOMIC_BOOL_COMPARE_AND_SWAP,
[official-gcc.git] / libgfortran / io / fbuf.c
blobe1daa0d32d6274d0426eb7e4226a97e1a3a6f0dc
1 /* Copyright (C) 2008, 2009 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 <string.h>
28 #include <stdlib.h>
31 //#define FBUF_DEBUG
34 void
35 fbuf_init (gfc_unit * u, int len)
37 if (len == 0)
38 len = 512; /* Default size. */
40 u->fbuf = get_mem (sizeof (fbuf));
41 u->fbuf->buf = get_mem (len);
42 u->fbuf->len = len;
43 u->fbuf->act = u->fbuf->pos = 0;
47 void
48 fbuf_destroy (gfc_unit * u)
50 if (u->fbuf == NULL)
51 return;
52 if (u->fbuf->buf)
53 free_mem (u->fbuf->buf);
54 free_mem (u->fbuf);
55 u->fbuf = NULL;
59 static void
60 #ifdef FBUF_DEBUG
61 fbuf_debug (gfc_unit * u, const char * format, ...)
63 va_list args;
64 va_start(args, format);
65 vfprintf(stderr, format, args);
66 va_end(args);
67 fprintf (stderr, "fbuf_debug pos: %d, act: %d, buf: ''",
68 u->fbuf->pos, u->fbuf->act);
69 for (int ii = 0; ii < u->fbuf->act; ii++)
71 putc (u->fbuf->buf[ii], stderr);
73 fprintf (stderr, "''\n");
75 #else
76 fbuf_debug (gfc_unit * u __attribute__ ((unused)),
77 const char * format __attribute__ ((unused)),
78 ...) {}
79 #endif
83 /* You should probably call this before doing a physical seek on the
84 underlying device. Returns how much the physical position was
85 modified. */
87 int
88 fbuf_reset (gfc_unit * u)
90 int seekval = 0;
92 if (!u->fbuf)
93 return 0;
95 fbuf_debug (u, "fbuf_reset: ");
96 fbuf_flush (u, u->mode);
97 /* If we read past the current position, seek the underlying device
98 back. */
99 if (u->mode == READING && u->fbuf->act > u->fbuf->pos)
101 seekval = - (u->fbuf->act - u->fbuf->pos);
102 fbuf_debug (u, "fbuf_reset seekval %d, ", seekval);
104 u->fbuf->act = u->fbuf->pos = 0;
105 return seekval;
109 /* Return a pointer to the current position in the buffer, and increase
110 the pointer by len. Makes sure that the buffer is big enough,
111 reallocating if necessary. */
113 char *
114 fbuf_alloc (gfc_unit * u, int len)
116 int newlen;
117 char *dest;
118 fbuf_debug (u, "fbuf_alloc len %d, ", len);
119 if (u->fbuf->pos + len > u->fbuf->len)
121 /* Round up to nearest multiple of the current buffer length. */
122 newlen = ((u->fbuf->pos + len) / u->fbuf->len + 1) * u->fbuf->len;
123 dest = realloc (u->fbuf->buf, newlen);
124 if (dest == NULL)
125 return NULL;
126 u->fbuf->buf = dest;
127 u->fbuf->len = newlen;
130 dest = u->fbuf->buf + u->fbuf->pos;
131 u->fbuf->pos += len;
132 if (u->fbuf->pos > u->fbuf->act)
133 u->fbuf->act = u->fbuf->pos;
134 return dest;
138 /* mode argument is WRITING for write mode and READING for read
139 mode. Return value is 0 for success, -1 on failure. */
142 fbuf_flush (gfc_unit * u, unit_mode mode)
144 int nwritten;
146 if (!u->fbuf)
147 return 0;
149 fbuf_debug (u, "fbuf_flush with mode %d: ", mode);
151 if (mode == WRITING)
153 if (u->fbuf->pos > 0)
155 nwritten = swrite (u->s, u->fbuf->buf, u->fbuf->pos);
156 if (nwritten < 0)
157 return -1;
160 /* Salvage remaining bytes for both reading and writing. This
161 happens with the combination of advance='no' and T edit
162 descriptors leaving the final position somewhere not at the end
163 of the record. For reading, this also happens if we sread() past
164 the record boundary. */
165 if (u->fbuf->act > u->fbuf->pos && u->fbuf->pos > 0)
166 memmove (u->fbuf->buf, u->fbuf->buf + u->fbuf->pos,
167 u->fbuf->act - u->fbuf->pos);
169 u->fbuf->act -= u->fbuf->pos;
170 u->fbuf->pos = 0;
172 return 0;
177 fbuf_seek (gfc_unit * u, int off, int whence)
179 if (!u->fbuf)
180 return -1;
182 switch (whence)
184 case SEEK_SET:
185 break;
186 case SEEK_CUR:
187 off += u->fbuf->pos;
188 break;
189 case SEEK_END:
190 off += u->fbuf->act;
191 break;
192 default:
193 return -1;
196 fbuf_debug (u, "fbuf_seek, off %d ", off);
197 /* The start of the buffer is always equal to the left tab
198 limit. Moving to the left past the buffer is illegal in C and
199 would also imply moving past the left tab limit, which is never
200 allowed in Fortran. Similarly, seeking past the end of the buffer
201 is not possible, in that case the user must make sure to allocate
202 space with fbuf_alloc(). So return error if that is
203 attempted. */
204 if (off < 0 || off > u->fbuf->act)
205 return -1;
206 u->fbuf->pos = off;
207 return off;
211 /* Fill the buffer with bytes for reading. Returns a pointer to start
212 reading from. If we hit EOF, returns a short read count. If any
213 other error occurs, return NULL. After reading, the caller is
214 expected to call fbuf_seek to update the position with the number
215 of bytes actually processed. */
217 char *
218 fbuf_read (gfc_unit * u, int * len)
220 char *ptr;
221 int oldact, oldpos;
222 int readlen = 0;
224 fbuf_debug (u, "fbuf_read, len %d: ", *len);
225 oldact = u->fbuf->act;
226 oldpos = u->fbuf->pos;
227 ptr = fbuf_alloc (u, *len);
228 u->fbuf->pos = oldpos;
229 if (oldpos + *len > oldact)
231 fbuf_debug (u, "reading %d bytes starting at %d ",
232 oldpos + *len - oldact, oldact);
233 readlen = sread (u->s, u->fbuf->buf + oldact, oldpos + *len - oldact);
234 if (readlen < 0)
235 return NULL;
236 *len = oldact - oldpos + readlen;
238 u->fbuf->act = oldact + readlen;
239 fbuf_debug (u, "fbuf_read done: ");
240 return ptr;
244 /* When the fbuf_getc() inline function runs out of buffer space, it
245 calls this function to fill the buffer with bytes for
246 reading. Never call this function directly. */
249 fbuf_getc_refill (gfc_unit * u)
251 int nread;
252 char *p;
254 fbuf_debug (u, "fbuf_getc_refill ");
256 /* Read 80 bytes (average line length?). This is a compromise
257 between not needing to call the read() syscall all the time and
258 not having to memmove unnecessary stuff when switching to the
259 next record. */
260 nread = 80;
262 p = fbuf_read (u, &nread);
264 if (p && nread > 0)
265 return (unsigned char) u->fbuf->buf[u->fbuf->pos++];
266 else
267 return EOF;