1 /* Copyright (C) 2008, 2009, 2010, 2012 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)
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/>. */
37 fbuf_init (gfc_unit
* u
, int len
)
40 len
= 512; /* Default size. */
42 u
->fbuf
= xmalloc (sizeof (struct fbuf
));
43 u
->fbuf
->buf
= xmalloc (len
);
45 u
->fbuf
->act
= u
->fbuf
->pos
= 0;
50 fbuf_destroy (gfc_unit
* u
)
62 fbuf_debug (gfc_unit
* u
, const char * format
, ...)
65 va_start(args
, format
);
66 vfprintf(stderr
, format
, 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");
77 fbuf_debug (gfc_unit
* u
__attribute__ ((unused
)),
78 const char * format
__attribute__ ((unused
)),
84 /* You should probably call this before doing a physical seek on the
85 underlying device. Returns how much the physical position was
89 fbuf_reset (gfc_unit
* u
)
96 fbuf_debug (u
, "fbuf_reset: ");
97 fbuf_flush (u
, u
->mode
);
98 /* If we read past the current position, seek the underlying device
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;
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. */
115 fbuf_alloc (gfc_unit
* u
, int len
)
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
);
128 u
->fbuf
->len
= newlen
;
131 dest
= u
->fbuf
->buf
+ u
->fbuf
->pos
;
133 if (u
->fbuf
->pos
> u
->fbuf
->act
)
134 u
->fbuf
->act
= u
->fbuf
->pos
;
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
)
150 fbuf_debug (u
, "fbuf_flush with mode %d: ", mode
);
154 if (u
->fbuf
->pos
> 0)
156 nwritten
= swrite (u
->s
, u
->fbuf
->buf
, u
->fbuf
->pos
);
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
;
178 fbuf_seek (gfc_unit
* u
, int off
, int whence
)
197 fbuf_debug (u
, "fbuf_seek, off %d ", off
);
198 /* The start of the buffer is always equal to the left tab
199 limit. Moving to the left past the buffer is illegal in C and
200 would also imply moving past the left tab limit, which is never
201 allowed in Fortran. Similarly, seeking past the end of the buffer
202 is not possible, in that case the user must make sure to allocate
203 space with fbuf_alloc(). So return error if that is
205 if (off
< 0 || off
> u
->fbuf
->act
)
212 /* Fill the buffer with bytes for reading. Returns a pointer to start
213 reading from. If we hit EOF, returns a short read count. If any
214 other error occurs, return NULL. After reading, the caller is
215 expected to call fbuf_seek to update the position with the number
216 of bytes actually processed. */
219 fbuf_read (gfc_unit
* u
, int * len
)
225 fbuf_debug (u
, "fbuf_read, len %d: ", *len
);
226 oldact
= u
->fbuf
->act
;
227 oldpos
= u
->fbuf
->pos
;
228 ptr
= fbuf_alloc (u
, *len
);
229 u
->fbuf
->pos
= oldpos
;
230 if (oldpos
+ *len
> oldact
)
232 fbuf_debug (u
, "reading %d bytes starting at %d ",
233 oldpos
+ *len
- oldact
, oldact
);
234 readlen
= sread (u
->s
, u
->fbuf
->buf
+ oldact
, oldpos
+ *len
- oldact
);
237 *len
= oldact
- oldpos
+ readlen
;
239 u
->fbuf
->act
= oldact
+ readlen
;
240 fbuf_debug (u
, "fbuf_read done: ");
245 /* When the fbuf_getc() inline function runs out of buffer space, it
246 calls this function to fill the buffer with bytes for
247 reading. Never call this function directly. */
250 fbuf_getc_refill (gfc_unit
* u
)
255 fbuf_debug (u
, "fbuf_getc_refill ");
257 /* Read 80 bytes (average line length?). This is a compromise
258 between not needing to call the read() syscall all the time and
259 not having to memmove unnecessary stuff when switching to the
263 p
= fbuf_read (u
, &nread
);
266 return (unsigned char) u
->fbuf
->buf
[u
->fbuf
->pos
++];