2018-03-08 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgfortran / io / intrinsics.c
blob032ae2d1bc1d4ed239eb0363d73e117841f24be0
1 /* Implementation of the FGET, FGETC, FPUT, FPUTC, FLUSH
2 FTELL, TTYNAM and ISATTY intrinsics.
3 Copyright (C) 2005-2018 Free Software Foundation, Inc.
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "io.h"
27 #include "fbuf.h"
28 #include "unix.h"
29 #include <string.h>
32 static const int five = 5;
33 static const int six = 6;
35 extern int PREFIX(fgetc) (const int *, char *, gfc_charlen_type);
36 export_proto_np(PREFIX(fgetc));
38 int
39 PREFIX(fgetc) (const int *unit, char *c, gfc_charlen_type c_len)
41 int ret;
42 gfc_unit *u = find_unit (*unit);
44 if (u == NULL)
45 return -1;
47 fbuf_reset (u);
48 if (u->mode == WRITING)
50 sflush (u->s);
51 u->mode = READING;
54 memset (c, ' ', c_len);
55 ret = sread (u->s, c, 1);
56 unlock_unit (u);
58 if (ret < 0)
59 return ret;
61 if (ret != 1)
62 return -1;
63 else
64 return 0;
68 #define FGETC_SUB(kind) \
69 extern void fgetc_i ## kind ## _sub \
70 (const int *, char *, GFC_INTEGER_ ## kind *, gfc_charlen_type); \
71 export_proto(fgetc_i ## kind ## _sub); \
72 void fgetc_i ## kind ## _sub \
73 (const int *unit, char *c, GFC_INTEGER_ ## kind *st, gfc_charlen_type c_len) \
74 { if (st != NULL) \
75 *st = PREFIX(fgetc) (unit, c, c_len); \
76 else \
77 PREFIX(fgetc) (unit, c, c_len); }
79 FGETC_SUB(1)
80 FGETC_SUB(2)
81 FGETC_SUB(4)
82 FGETC_SUB(8)
85 extern int PREFIX(fget) (char *, gfc_charlen_type);
86 export_proto_np(PREFIX(fget));
88 int
89 PREFIX(fget) (char *c, gfc_charlen_type c_len)
91 return PREFIX(fgetc) (&five, c, c_len);
95 #define FGET_SUB(kind) \
96 extern void fget_i ## kind ## _sub \
97 (char *, GFC_INTEGER_ ## kind *, gfc_charlen_type); \
98 export_proto(fget_i ## kind ## _sub); \
99 void fget_i ## kind ## _sub \
100 (char *c, GFC_INTEGER_ ## kind *st, gfc_charlen_type c_len) \
101 { if (st != NULL) \
102 *st = PREFIX(fgetc) (&five, c, c_len); \
103 else \
104 PREFIX(fgetc) (&five, c, c_len); }
106 FGET_SUB(1)
107 FGET_SUB(2)
108 FGET_SUB(4)
109 FGET_SUB(8)
113 extern int PREFIX(fputc) (const int *, char *, gfc_charlen_type);
114 export_proto_np(PREFIX(fputc));
117 PREFIX(fputc) (const int *unit, char *c,
118 gfc_charlen_type c_len __attribute__((unused)))
120 ssize_t s;
121 gfc_unit *u = find_unit (*unit);
123 if (u == NULL)
124 return -1;
126 fbuf_reset (u);
127 if (u->mode == READING)
129 sflush (u->s);
130 u->mode = WRITING;
133 s = swrite (u->s, c, 1);
134 unlock_unit (u);
135 if (s < 0)
136 return -1;
137 return 0;
141 #define FPUTC_SUB(kind) \
142 extern void fputc_i ## kind ## _sub \
143 (const int *, char *, GFC_INTEGER_ ## kind *, gfc_charlen_type); \
144 export_proto(fputc_i ## kind ## _sub); \
145 void fputc_i ## kind ## _sub \
146 (const int *unit, char *c, GFC_INTEGER_ ## kind *st, gfc_charlen_type c_len) \
147 { if (st != NULL) \
148 *st = PREFIX(fputc) (unit, c, c_len); \
149 else \
150 PREFIX(fputc) (unit, c, c_len); }
152 FPUTC_SUB(1)
153 FPUTC_SUB(2)
154 FPUTC_SUB(4)
155 FPUTC_SUB(8)
158 extern int PREFIX(fput) (char *, gfc_charlen_type);
159 export_proto_np(PREFIX(fput));
162 PREFIX(fput) (char *c, gfc_charlen_type c_len)
164 return PREFIX(fputc) (&six, c, c_len);
168 #define FPUT_SUB(kind) \
169 extern void fput_i ## kind ## _sub \
170 (char *, GFC_INTEGER_ ## kind *, gfc_charlen_type); \
171 export_proto(fput_i ## kind ## _sub); \
172 void fput_i ## kind ## _sub \
173 (char *c, GFC_INTEGER_ ## kind *st, gfc_charlen_type c_len) \
174 { if (st != NULL) \
175 *st = PREFIX(fputc) (&six, c, c_len); \
176 else \
177 PREFIX(fputc) (&six, c, c_len); }
179 FPUT_SUB(1)
180 FPUT_SUB(2)
181 FPUT_SUB(4)
182 FPUT_SUB(8)
185 /* SUBROUTINE FLUSH(UNIT)
186 INTEGER, INTENT(IN), OPTIONAL :: UNIT */
188 extern void flush_i4 (GFC_INTEGER_4 *);
189 export_proto(flush_i4);
191 void
192 flush_i4 (GFC_INTEGER_4 *unit)
194 gfc_unit *us;
196 /* flush all streams */
197 if (unit == NULL)
198 flush_all_units ();
199 else
201 us = find_unit (*unit);
202 if (us != NULL)
204 sflush (us->s);
205 unlock_unit (us);
211 extern void flush_i8 (GFC_INTEGER_8 *);
212 export_proto(flush_i8);
214 void
215 flush_i8 (GFC_INTEGER_8 *unit)
217 gfc_unit *us;
219 /* flush all streams */
220 if (unit == NULL)
221 flush_all_units ();
222 else
224 us = find_unit (*unit);
225 if (us != NULL)
227 sflush (us->s);
228 unlock_unit (us);
233 /* FSEEK intrinsic */
235 extern void fseek_sub (int *, GFC_IO_INT *, int *, int *);
236 export_proto(fseek_sub);
238 void
239 fseek_sub (int *unit, GFC_IO_INT *offset, int *whence, int *status)
241 gfc_unit *u = find_unit (*unit);
242 ssize_t result = -1;
244 if (u != NULL)
246 result = sseek(u->s, *offset, *whence);
248 unlock_unit (u);
251 if (status)
252 *status = (result < 0 ? -1 : 0);
257 /* FTELL intrinsic */
259 static gfc_offset
260 gf_ftell (int unit)
262 gfc_unit *u = find_unit (unit);
263 if (u == NULL)
264 return -1;
265 int pos = fbuf_reset (u);
266 if (pos != 0)
267 sseek (u->s, pos, SEEK_CUR);
268 gfc_offset ret = stell (u->s);
269 unlock_unit (u);
270 return ret;
274 extern GFC_IO_INT PREFIX(ftell) (int *);
275 export_proto_np(PREFIX(ftell));
277 GFC_IO_INT
278 PREFIX(ftell) (int *unit)
280 return gf_ftell (*unit);
284 #define FTELL_SUB(kind) \
285 extern void ftell_i ## kind ## _sub (int *, GFC_INTEGER_ ## kind *); \
286 export_proto(ftell_i ## kind ## _sub); \
287 void \
288 ftell_i ## kind ## _sub (int *unit, GFC_INTEGER_ ## kind *offset) \
290 *offset = gf_ftell (*unit); \
293 FTELL_SUB(1)
294 FTELL_SUB(2)
295 FTELL_SUB(4)
296 FTELL_SUB(8)
300 /* LOGICAL FUNCTION ISATTY(UNIT)
301 INTEGER, INTENT(IN) :: UNIT */
303 extern GFC_LOGICAL_4 isatty_l4 (int *);
304 export_proto(isatty_l4);
306 GFC_LOGICAL_4
307 isatty_l4 (int *unit)
309 gfc_unit *u;
310 GFC_LOGICAL_4 ret = 0;
312 u = find_unit (*unit);
313 if (u != NULL)
315 ret = (GFC_LOGICAL_4) stream_isatty (u->s);
316 unlock_unit (u);
318 return ret;
322 extern GFC_LOGICAL_8 isatty_l8 (int *);
323 export_proto(isatty_l8);
325 GFC_LOGICAL_8
326 isatty_l8 (int *unit)
328 gfc_unit *u;
329 GFC_LOGICAL_8 ret = 0;
331 u = find_unit (*unit);
332 if (u != NULL)
334 ret = (GFC_LOGICAL_8) stream_isatty (u->s);
335 unlock_unit (u);
337 return ret;
341 /* SUBROUTINE TTYNAM(UNIT,NAME)
342 INTEGER,SCALAR,INTENT(IN) :: UNIT
343 CHARACTER,SCALAR,INTENT(OUT) :: NAME */
345 extern void ttynam_sub (int *, char *, gfc_charlen_type);
346 export_proto(ttynam_sub);
348 void
349 ttynam_sub (int *unit, char *name, gfc_charlen_type name_len)
351 gfc_unit *u;
352 int nlen;
353 int err = 1;
355 u = find_unit (*unit);
356 if (u != NULL)
358 err = stream_ttyname (u->s, name, name_len);
359 if (err == 0)
361 nlen = strlen (name);
362 memset (&name[nlen], ' ', name_len - nlen);
365 unlock_unit (u);
367 if (err != 0)
368 memset (name, ' ', name_len);
372 extern void ttynam (char **, gfc_charlen_type *, int);
373 export_proto(ttynam);
375 void
376 ttynam (char **name, gfc_charlen_type *name_len, int unit)
378 gfc_unit *u;
380 u = find_unit (unit);
381 if (u != NULL)
383 *name = xmalloc (TTY_NAME_MAX);
384 int err = stream_ttyname (u->s, *name, TTY_NAME_MAX);
385 if (err == 0)
387 *name_len = strlen (*name);
388 unlock_unit (u);
389 return;
391 free (*name);
392 unlock_unit (u);
395 *name_len = 0;
396 *name = NULL;