a68g-io.c
1 //! @file a68g-io.c
2 //! @author J. Marcel van der Veer
3
4 //! @section Copyright
5 //!
6 //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
7 //! Copyright 2001-2024 J. Marcel van der Veer [algol68g@xs4all.nl].
8
9 //! @section License
10 //!
11 //! This program is free software; you can redistribute it and/or modify it
12 //! under the terms of the GNU General Public License as published by the
13 //! Free Software Foundation; either version 3 of the License, or
14 //! (at your option) any later version.
15 //!
16 //! This program is distributed in the hope that it will be useful, but
17 //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 //! more details. You should have received a copy of the GNU General Public
20 //! License along with this program. If not, see [http://www.gnu.org/licenses/].
21
22 //! @section Synopsis
23 //!
24 //! Low-level input-output routines.
25
26 #include "a68g.h"
27 #include "a68g-prelude.h"
28
29 //! @brief Initialise output to STDOUT.
30
31 void init_tty (void)
32 {
33 A68 (chars_in_stderr) = 0;
34 A68 (chars_in_stdout) = 0;
35 A68 (halt_typing) = A68_FALSE;
36 change_masks (TOP_NODE (&A68_JOB), BREAKPOINT_INTERRUPT_MASK, A68_FALSE);
37 }
38
39 //! @brief Terminate current line on STDOUT.
40
41 void io_close_tty_line (void)
42 {
43 if (A68 (chars_in_stderr) > 0) {
44 A68 (chars_in_stderr) = 0;
45 io_write_string (A68_STDERR, NEWLINE_STRING);
46 }
47 if (A68 (chars_in_stdout) > 0) {
48 A68 (chars_in_stdout) = 0;
49 io_write_string (A68_STDOUT, NEWLINE_STRING);
50 }
51 }
52
53 //! @brief Get a char from STDIN.
54
55 char get_stdin_char (void)
56 {
57 char ch[4];
58 errno = 0;
59 ssize_t j = io_read_conv (A68_STDIN, &(ch[0]), 1);
60 ABEND (j < 0, ERROR_ACTION, __func__);
61 return (char) (j == 1 ? ch[0] : EOF_CHAR);
62 }
63
64 //! @brief Read string from STDIN, until NEWLINE_STRING.
65
66 char *read_string_from_tty (char *prompt)
67 {
68 #if defined (HAVE_READLINE)
69 char *line = readline (prompt);
70 if (line != NO_TEXT && (int) strlen (line) > 0) {
71 add_history (line);
72 }
73 a68_bufcpy (A68 (input_line), line, BUFFER_SIZE);
74 A68 (chars_in_stdout) = (int) strlen (A68 (input_line));
75 a68_free (line);
76 return A68 (input_line);
77 #else
78 int ch, k = 0, n;
79 if (prompt != NO_TEXT) {
80 io_close_tty_line ();
81 io_write_string (A68_STDOUT, prompt);
82 }
83 ch = get_stdin_char ();
84 while (ch != NEWLINE_CHAR && k < BUFFER_SIZE - 1) {
85 if (ch == EOF_CHAR) {
86 A68 (input_line)[0] = EOF_CHAR;
87 A68 (input_line)[1] = NULL_CHAR;
88 A68 (chars_in_stdout) = 1;
89 return A68 (input_line);
90 } else {
91 A68 (input_line)[k++] = (char) ch;
92 ch = get_stdin_char ();
93 }
94 }
95 A68 (input_line)[k] = NULL_CHAR;
96 n = (int) strlen (A68 (input_line));
97 A68 (chars_in_stdout) = (ch == NEWLINE_CHAR ? 0 : (n > 0 ? n : 1));
98 return A68 (input_line);
99 #endif
100 }
101
102 //! @brief Write string to file.
103
104 void io_write_string (FILE_T f, const char *z)
105 {
106 errno = 0;
107 if (f != A68_STDOUT && f != A68_STDERR) {
108 // Writing to file.
109 ssize_t j = io_write_conv (f, z, strlen (z));
110 ABEND (j < 0, ERROR_ACTION, __func__);
111 } else {
112 // Writing to TTY parts until end-of-string.
113 int first = 0, k;
114 do {
115 k = first;
116 // How far can we get?.
117 while (z[k] != NULL_CHAR && z[k] != NEWLINE_CHAR) {
118 k++;
119 }
120 if (k > first) {
121 // Write these characters.
122 int n = k - first;
123 ssize_t j = io_write_conv (f, &(z[first]), (size_t) n);
124 ABEND (j < 0, ERROR_ACTION, __func__);
125 if (f == A68_STDERR) {
126 A68 (chars_in_stderr) += n;
127 } else {
128 A68 (chars_in_stdout) += n;
129 }
130 }
131 if (z[k] == NEWLINE_CHAR) {
132 // Pretty-print newline.
133 k++;
134 first = k;
135 ssize_t j = io_write_conv (f, NEWLINE_STRING, 1);
136 ABEND (j < 0, ERROR_ACTION, __func__);
137 if (f == A68_STDERR) {
138 A68 (chars_in_stderr) = 0;
139 } else {
140 A68 (chars_in_stdout) = 0;
141 }
142 }
143 } while (z[k] != NULL_CHAR);
144 }
145 }
146
147 //! @brief Read bytes from file into buffer.
148
149 ssize_t io_read (FILE_T fd, void *buf, size_t n)
150 {
151 size_t to_do = n;
152 int restarts = 0;
153 char *z = (char *) buf;
154 while (to_do > 0) {
155 #if defined (BUILD_WIN32)
156 int bytes_read;
157 #else
158 ssize_t bytes_read;
159 #endif
160 errno = 0;
161 bytes_read = read (fd, z, to_do);
162 if (bytes_read < 0) {
163 if (errno == EINTR) {
164 // interrupt, retry.
165 bytes_read = 0;
166 if (restarts++ > MAX_RESTART) {
167 return -1;
168 }
169 } else {
170 // read error.
171 return -1;
172 }
173 } else if (bytes_read == 0) {
174 break; // EOF_CHAR
175 }
176 to_do -= (size_t) bytes_read;
177 z += bytes_read;
178 }
179 return (ssize_t) n - (ssize_t) to_do; // return >= 0
180 }
181
182 //! @brief Writes n bytes from buffer to file.
183
184 ssize_t io_write (FILE_T fd, const void *buf, size_t n)
185 {
186 size_t to_do = n;
187 int restarts = 0;
188 char *z = (char *) buf;
189 while (to_do > 0) {
190 ssize_t bytes_written;
191 errno = 0;
192 bytes_written = write (fd, z, to_do);
193 if (bytes_written <= 0) {
194 if (errno == EINTR) {
195 // interrupt, retry.
196 bytes_written = 0;
197 if (restarts++ > MAX_RESTART) {
198 return -1;
199 }
200 } else {
201 // write error.
202 return -1;
203 }
204 }
205 to_do -= (size_t) bytes_written;
206 z += bytes_written;
207 }
208 return (ssize_t) n;
209 }
210
211 //! @brief Read bytes from file into buffer.
212
213 ssize_t io_read_conv (FILE_T fd, void *buf, size_t n)
214 {
215 size_t to_do = n;
216 int restarts = 0;
217 char *z = (char *) buf;
218 while (to_do > 0) {
219 #if defined (BUILD_WIN32)
220 int bytes_read;
221 #else
222 ssize_t bytes_read;
223 #endif
224 errno = 0;
225 bytes_read = read (fd, z, to_do);
226 if (bytes_read < 0) {
227 if (errno == EINTR) {
228 // interrupt, retry.
229 bytes_read = 0;
230 if (restarts++ > MAX_RESTART) {
231 return -1;
232 }
233 } else {
234 // read error.
235 return -1;
236 }
237 } else if (bytes_read == 0) {
238 break; // EOF_CHAR
239 }
240 to_do -= (size_t) bytes_read;
241 z += bytes_read;
242 }
243 return (ssize_t) n - (ssize_t) to_do;
244 }
245
246 //! @brief Writes n bytes from buffer to file.
247
248 ssize_t io_write_conv (FILE_T fd, const void *buf, size_t n)
249 {
250 size_t to_do = n;
251 int restarts = 0;
252 char *z = (char *) buf;
253 while (to_do > 0) {
254 ssize_t bytes_written;
255 errno = 0;
256 bytes_written = write (fd, z, to_do);
257 if (bytes_written <= 0) {
258 if (errno == EINTR) {
259 // interrupt, retry.
260 bytes_written = 0;
261 if (restarts++ > MAX_RESTART) {
262 return -1;
263 }
264 } else {
265 // write error.
266 return -1;
267 }
268 }
269 to_do -= (size_t) bytes_written;
270 z += bytes_written;
271 }
272 return (ssize_t) n;
273 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|