transput.c
1 //! @file transput.c
2 //! @author J. Marcel van der Veer
3 //
4 //! @section Copyright
5 //
6 // This file is part of VIF - vintage FORTRAN compiler.
7 // Copyright 2020-2025 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 //! Compile Fortran IO.
25
26 #include <vif.h>
27
28 static char *unum (EXPR *unit)
29 {
30 if (unit->mode.type == INTEGER) {
31 return unit->str;
32 } else {
33 return "0";
34 }
35 }
36
37 void save_iostat (char *iostat)
38 {
39 if (iostat != NO_TEXT) {
40 EXPR loc;
41 NEW_RECORD (ios);
42 NEW_RECORD (str);
43 MODE mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
44 _srecordf (ios, "%s", iostat);
45 RECCLR (loc.str);
46 factor_variable (&loc, NULL, &mode, ios);
47 if (loc.mode.type == mode.type && loc.mode.len == mode.len) {
48 _srecordf (str, "%s_ = errno;\n", loc.str);
49 code (nprocs, BODY, str);
50 } else {
51 MODE_ERROR (3301, qtype (&(loc.mode)), qtype (&mode));
52 }
53 }
54 }
55
56 void io_event (char *proc, EXPR *unit, char *iorc, LBL *endlbl, LBL *errlbl)
57 {
58 if (EQUAL (proc, "write")) {
59 NEW_RECORD (str);
60 if (errlbl == NO_LABEL) {
61 _srecordf (str, "_write_err (%s, %s, _ioerr_%s (\"%s\", %s));\n", iorc, unum (unit), proc, stat_start, unum (unit));
62 } else {
63 _srecordf (str, "_write_err (%s, %s, goto _l%d);\n", iorc, unum (unit), errlbl->num);
64 }
65 code (nprocs, BODY, str);
66 } else if (EQUAL (proc, "read")) {
67 NEW_RECORD (str1);
68 NEW_RECORD (str2);
69 NEW_RECORD (str);
70 if (endlbl == NO_LABEL) {
71 _srecordf (str1, "_ioend_%s (\"%s\", %s)", proc, stat_start, unum (unit));
72 } else {
73 _srecordf (str1, "goto _l%d", endlbl->num);
74 }
75 if (errlbl == NO_LABEL) {
76 _srecordf (str2, "_ioerr_%s (\"%s\", %s)", proc, stat_start, unum (unit));
77 } else {
78 _srecordf (str2, "goto _l%d", errlbl->num);
79 }
80 _srecordf (str, "_read_err (%s, %s, %s, %s);\n", iorc, unum (unit), str1, str2);
81 code (nprocs, BODY, str);
82 } else {
83 BUG ("io_event");
84 }
85 }
86
87 void io_parm (EXPR *reg, char *elem)
88 {
89 if (reg->variant == EXPR_VAR) {
90 if (IS_ROW (reg->mode)) {
91 _srecordf (elem, "%s", reg->str);
92 } else if (reg->str[0] == '*') {
93 _srecordf (elem, "%s", ®->str[1]);
94 } else if (reg->mode.type == CHARACTER) {
95 _srecordf (elem, "%s", reg->str);
96 } else {
97 (void) impl_decl (reg->str, NO_MODE);
98 _srecordf (elem, "&%s", reg->str);
99 }
100 } else if (reg->variant == EXPR_SLICE) {
101 _srecordf (elem, "&%s", reg->str);
102 } else {
103 NEW_RECORD (tmp);
104 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
105 if (reg->mode.type == CHARACTER) {
106 norm_mode (®->mode);
107 if (reg->mode.len == 0) {
108 add_local (tmp, reg->mode.type, MAX_STRLEN, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
109 _srecordf (elem, "strcpy (%s, %s);\n", tmp, reg->str);
110 } else {
111 add_local (tmp, reg->mode.type, reg->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
112 _srecordf (elem, "bufcpy (%s, %s, %d);\n", tmp, reg->str, reg->mode.len);
113 }
114 code (nprocs, BODY, elem);
115 _srecordf (elem, "%s", tmp);
116 } else {
117 add_local (tmp, reg->mode.type, reg->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
118 _srecordf (elem, "%s = %s;\n", tmp, reg->str);
119 code (nprocs, BODY, elem);
120 _srecordf (elem, "&%s", tmp);
121 }
122 }
123 }
124
125 void io_text_items (char *proc, EXPR *unit, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, logical_4 term)
126 {
127 NEW_RECORD (str);
128 if (EQUAL (proc, "write")) {
129 _srecordf (str, "while (%s[%s] != NULL && %s[%s] == FMT_TEXT) {\n", fstr, fid, fstr, fid);
130 code (nprocs, BODY, str);
131 if (term) {
132 _srecordf (str, "if (%s[%s + 2] == FMT_TERM) {\n", fstr, fid);
133 code (nprocs, BODY, str);
134 code (nprocs, BODY, "break;\n");
135 code (nprocs, BODY, "}\n");
136 }
137 _srecordf (str, "%s = _vif_printf (%s, %s[%s + 2], NULL, NOTYPE, 0);\n", iorc, unum (unit), fstr, fid);
138 code (nprocs, BODY, str);
139 io_event (proc, unit, iorc, endlbl, errlbl);
140 _srecordf (str, "%s += 3;\n", fid);
141 code (nprocs, BODY, str);
142 code (nprocs, BODY, "}\n");
143 } else if (EQUAL (proc, "read")) {
144 _srecordf (str, "while (%s[%s] != NULL && %s[%s] == FMT_TEXT) {\n", fstr, fid, fstr, fid);
145 code (nprocs, BODY, str);
146 _srecordf (str, "%s = _vif_scanf (%s, %s[%s + 1], NULL, NOTYPE, 0);\n", iorc, unum (unit), fstr, fid);
147 code (nprocs, BODY, str);
148 io_event (proc, unit, iorc, endlbl, errlbl);
149 _srecordf (str, "%s += 3;\n", fid);
150 code (nprocs, BODY, str);
151 code (nprocs, BODY, "}\n");
152 }
153 }
154
155 void io_format (char *proc, EXPR *unit, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, char *elem, char *type, int_4 len)
156 {
157 NEW_RECORD (str);
158 if (EQUAL (proc, "write")) {
159 _srecordf (str, "if (%s[%s] == NULL) {\n", fstr, fid);
160 code (nprocs, BODY, str);
161 _srecordf (str, "%s = 0;\n", fid);
162 code (nprocs, BODY, str);
163 _srecordf (str, "%s = fprintf (_ffile[%s].unit, \"\\n\");\n", iorc, unum (unit));
164 code (nprocs, BODY, str);
165 io_text_items (proc, unit, fstr, fid, iorc, endlbl, errlbl, FALSE);
166 code (nprocs, BODY, "};\n");
167 _srecordf (str, "%s = _vif_printf (%s, %s[%s + 2], %s, %s, %d);\n", iorc, unum (unit), fstr, fid, elem, type, len);
168 code (nprocs, BODY, str);
169 io_event (proc, unit, iorc, endlbl, errlbl);
170 _srecordf (str, "%s += 3;\n", fid);
171 code (nprocs, BODY, str);
172 io_text_items (proc, unit, fstr, fid, iorc, endlbl, errlbl, TRUE);
173 } else if (EQUAL (proc, "read")) {
174 _srecordf (str, "if (%s[%s] == NULL) {\n", fstr, fid);
175 code (nprocs, BODY, str);
176 _srecordf (str, "%s = 0;\n", fid);
177 code (nprocs, BODY, str);
178 _srecordf (str, "_vif_scanf (%s, NULL, NULL, NOTYPE, 0);\n", unum (unit));
179 code (nprocs, BODY, str);
180 io_text_items (proc, unit, fstr, fid, iorc, endlbl, errlbl, FALSE);
181 code (nprocs, BODY, "};\n");
182 _srecordf (str, "%s = _vif_scanf (%s, %s[%s + 1], %s, %s, %d);\n", iorc, unum (unit), fstr, fid, elem, type, len);
183 code (nprocs, BODY, str);
184 io_event (proc, unit, iorc, endlbl, errlbl);
185 _srecordf (str, "%s += 3;\n", fid);
186 code (nprocs, BODY, str);
187 io_text_items (proc, unit, fstr, fid, iorc, endlbl, errlbl, FALSE);
188 }
189 }
190
191 void io_elemuf (char *proc, EXPR *unit, EXPR *reg, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
192 {
193 NEW_RECORD (str);
194 NEW_RECORD (elem);
195 io_parm (reg, elem);
196 if (EQUAL (proc, "write")) {
197 _srecordf (str, "%s = fwrite (%s", iorc, elem);
198 code (nprocs, BODY, str);
199 } else if (EQUAL (proc, "read")) {
200 _srecordf (str, "%s = fread (%s", iorc, elem);
201 code (nprocs, BODY, str);
202 } else {
203 BUG ("io_elemuf");
204 }
205 _srecordf (str, ", sizeof (%s), ", wtype (®->mode, NOARG, NOFUN));
206 code (nprocs, BODY, str);
207 if (reg->variant == EXPR_VAR && IS_ROW (reg->mode)) {
208 code_row_len (reg->idf);
209 } else {
210 code (nprocs, BODY, "1");
211 }
212 _srecordf (str, ", _ffile[%s].unit);\n", unum (unit));
213 code (nprocs, BODY, str);
214 io_event (proc, unit, iorc, endlbl, errlbl);
215 }
216
217 void io_elemstd (char *proc, EXPR *unit, EXPR *reg, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
218 {
219 NEW_RECORD (str);
220 NEW_RECORD (elem);
221 io_parm (reg, elem);
222 if (reg->mode.type == INTEGER) {
223 if (EQUAL (proc, "write")) {
224 _srecordf (str, "%s = _vif_printf (%s, \"%%d\", %s, INTEGER, %d);\n", iorc, unum (unit), elem, reg->mode.len);
225 } else if (EQUAL (proc, "read")) {
226 _srecordf (str, "%s = _vif_scanf (%s, \"%%d\", %s, INTEGER, %d);\n", iorc, unum (unit), elem, reg->mode.len);
227 }
228 } else if (reg->mode.type == LOGICAL) {
229 if (EQUAL (proc, "write")) {
230 _srecordf (str, "%s = _vif_printf (%s, \"%%c\", %s, LOGICAL, %d);\n", iorc, unum (unit), elem, reg->mode.len);
231 } else if (EQUAL (proc, "read")) {
232 _srecordf (str, "%s = _vif_scanf (%s, \"%%c\", %s, LOGICAL, %d);\n", iorc, unum (unit), elem, reg->mode.len);
233 }
234 } else if (reg->mode.type == REAL) {
235 if (EQUAL (proc, "write")) {
236 NEW_RECORD (fmt);
237 if (reg->mode.len == 32) {
238 _srecordf (fmt, "\"%%.%de\"", FLT256_DIG);
239 _srecordf (str, "%s = _vif_printf (%s, %s, %s, REAL, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
240 } else if (reg->mode.len == 16) {
241 _srecordf (fmt, "\"%%.%de\"", FLT128_DIG);
242 _srecordf (str, "%s = _vif_printf (%s, %s, %s, REAL, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
243 } else if (reg->mode.len == 8) {
244 _srecordf (fmt, "\"%%.%de\"", DBL_DIG);
245 _srecordf (str, "%s = _vif_printf (%s, %s, %s, REAL, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
246 } else if (reg->mode.len == 4) {
247 _srecordf (fmt, "\"%%.%de\"", FLT_DIG);
248 _srecordf (str, "%s = _vif_printf (%s, %s, %s, REAL, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
249 }
250 } else if (EQUAL (proc, "read")) {
251 _srecordf (str, "%s = _vif_scanf (%s, \"%%e\", %s, REAL, %d);\n", iorc, unum (unit), elem, reg->mode.len);
252 }
253 } else if (reg->mode.type == COMPLEX) {
254 if (EQUAL (proc, "write")) {
255 NEW_RECORD (fmt);
256 if (reg->mode.len == 8) {
257 _srecordf (fmt, "\"%%.%de\"", FLT_DIG);
258 } else if (reg->mode.len == 16) {
259 _srecordf (fmt, "\"%%.%de\"", DBL_DIG);
260 } else if (reg->mode.len == 32) {
261 _srecordf (fmt, "\"%%.%de\"", FLT128_DIG);
262 } else if (reg->mode.len == 64) {
263 _srecordf (fmt, "\"%%.%de\"", FLT256_DIG);
264 }
265 _srecordf (str, "%s = _vif_printf (%s, %s, %s, COMPLEX, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
266 code (nprocs, BODY, str);
267 io_event (proc, unit, iorc, endlbl, errlbl);
268 _srecordf (str, "%s = _vif_printf (%s, \" \", NULL, NOTYPE, 0);\n", iorc, unum (unit));
269 code (nprocs, BODY, str);
270 io_event (proc, unit, iorc, endlbl, errlbl);
271 _srecordf (str, "%s = _vif_printf (%s, %s, %s, COMPLEX, -%d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
272 } else if (EQUAL (proc, "read")) {
273 _srecordf (str, "%s = _vif_scanf (%s, \"%%e\", %s, COMPLEX, %d);\n", iorc, unum (unit), elem, reg->mode.len);
274 code (nprocs, BODY, str);
275 io_event (proc, unit, iorc, endlbl, errlbl);
276 _srecordf (str, "%s = _vif_scanf (%s, \"%%e\", %s, COMPLEX, -%d);\n", iorc, unum (unit), elem, reg->mode.len);
277 }
278 } else if (reg->mode.type == CHARACTER) {
279 if (EQUAL (proc, "write")) {
280 // _srecordf (str, "%s = _vif_printf (%s, \"%%-%ds\", %s, CHARACTER, %d);\n", iorc, unum (unit), reg->mode.len, elem, reg->mode.len);
281 _srecordf (str, "%s = _vif_printf (%s, \"%%s\", %s, CHARACTER, %d);\n", iorc, unum (unit), elem, reg->mode.len);
282 } else if (EQUAL (proc, "read")) {
283 // _srecordf (str, "%s = _vif_scanf (%s, \"%%%ds\", %s, CHARACTER, %d);\n", iorc, unum (unit), reg->mode.len, elem, reg->mode.len);
284 _srecordf (str, "%s = _vif_scanf (%s, \"%%s\", %s, CHARACTER, %d);\n", iorc, unum (unit), elem, reg->mode.len);
285 }
286 }
287 code (nprocs, BODY, str);
288 io_event (proc, unit, iorc, endlbl, errlbl);
289 (*items) ++;
290 }
291
292 void io_elemf (char *proc, EXPR *unit, EXPR *reg, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
293 {
294 NEW_RECORD (elem);
295 io_parm (reg, elem);
296 if (reg->mode.type == INTEGER) {
297 io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "INTEGER", reg->mode.len);
298 (*items) ++;
299 } else if (reg->mode.type == LOGICAL) {
300 io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "LOGICAL", reg->mode.len);
301 (*items) ++;
302 } else if (reg->mode.type == REAL) {
303 io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "REAL", reg->mode.len);
304 (*items) ++;
305 } else if (reg->mode.type == COMPLEX) {
306 io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "COMPLEX", reg->mode.len);
307 io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "COMPLEX", -reg->mode.len);
308 (*items) ++;
309 } else if (reg->mode.type == CHARACTER) {
310 io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "CHARACTER", reg->mode.len);
311 (*items) ++;
312 }
313 }
314
315 void io_array (char *proc, EXPR *unit, EXPR *reg, int_4 form, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
316 {
317 NEW_RECORD (str); NEW_RECORD (tmpa); NEW_RECORD (tmpk);
318 EXPR elem;
319 IDENT *ptr;
320 _srecordf (tmpa, "_arr_%d", nloctmps++);
321 ptr = add_local (tmpa, reg->mode.type, reg->mode.len, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
322 ptr->alias = reg->idf;
323 _srecordf (tmpk, "_k_%d", nloctmps++);
324 add_local (tmpk, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
325 _srecordf (str, "for (%s = %s %s, %s = 0; %s < ", tmpa, ptr_to_array (ptr, NOCONST, CAST, ACTUAL), reg->str, tmpk, tmpk);
326 code (nprocs, BODY, str);
327 code_row_len (reg->idf);
328 _srecordf (str, "; %s++, %s++) {\n", tmpa, tmpk);
329 code (nprocs, BODY, str);
330 memcpy (&elem, reg, sizeof (EXPR));
331 elem.mode.dim = 0;
332 if (EQUAL (proc, "read")) {
333 _srecordf (elem.str, "%s", tmpa);
334 } else if (EQUAL (proc, "write")) {
335 _srecordf (elem.str, "*%s", tmpa);
336 } else {
337 BUG ("io_array");
338 }
339 if (form == STDFORMAT) {
340 io_elemstd (proc, unit, &elem, fstr, fid, iorc, endlbl, errlbl, items);
341 } else if (form == FORMATTED) {
342 io_elemf (proc, unit, &elem, fstr, fid, iorc, endlbl, errlbl, items);
343 }
344 code (nprocs, BODY, "}\n");
345 }
346
347 void io_elem (char *proc, EXPR *unit, int_4 form, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
348 {
349 EXPR reg;
350 express (®, NOTYPE, 0);
351 if (form == UNFORMATTED) {
352 io_elemuf (proc, unit, ®, iorc, endlbl, errlbl, items);
353 } else if (form == STDFORMAT) {
354 if (reg.variant == EXPR_VAR && IS_ROW (reg.mode)) {
355 io_array (proc, unit, ®, form, fstr, fid, iorc, endlbl, errlbl, items);
356 } else {
357 io_elemstd (proc, unit, ®, fstr, fid, iorc, endlbl, errlbl, items);
358 }
359 } else if (form == FORMATTED) {
360 if (reg.variant == EXPR_VAR && IS_ROW (reg.mode)) {
361 io_array (proc, unit, ®, form, fstr, fid, iorc, endlbl, errlbl, items);
362 } else {
363 io_elemf (proc, unit, ®, fstr, fid, iorc, endlbl, errlbl, items);
364 }
365 } else {
366 BUG ("IO formatting unspecified");
367 }
368 }
369
370 int_4 impl_do (void)
371 {
372 // Quick check whether (...) in a list is an implied DO loop.
373 int_4 rc, nest = 1;
374 while ((rc = scan (EXPECT_NONE)) != END_OF_LINE) {
375 if (TOKEN ("(")) {
376 nest++;
377 } else if (TOKEN (")")) {
378 nest--;
379 if (nest == 0) {
380 return FALSE;
381 }
382 } else if (nest == 1 && TOKEN (",")) {
383 // Trigger is the sequence ", I =" in outer nest.
384 rc = scan (EXPECT_NONE);
385 if (rc == WORD) {
386 NEW_RECORD (name);
387 RECCPY (name, curlex);
388 rc = scan (EXPECT_NONE);
389 if (TOKEN ("=")) {
390 (void) impl_decl (name, NO_MODE);
391 return TRUE;
392 } else {
393 UNSCAN;
394 }
395 }
396 }
397 }
398 (void) rc;
399 return FALSE;
400 }
401
402 void io_list (char *proc, EXPR *unit, int_4 form, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 lpatch, int_4 *nest, int_4 *items)
403 {
404 while (WITHIN) {
405 int_4 rc;
406 if (TOKEN (",")) {
407 rc = scan (EXPECT_NONE);
408 if (! WITHIN) {
409 SYNTAX (3302, prelex);
410 break;
411 }
412 if (TOKEN (",")) {
413 SYNTAX (3303, ",,");
414 continue;
415 }
416 } else {
417 rc = scan (EXPECT_NONE);
418 if (TOKEN (",")) {
419 continue;
420 }
421 }
422 if (! WITHIN) {
423 break;
424 }
425 if (TOKEN ("(")) {
426 SAVE_POS (1);
427 // Quick lookahead.
428 int_4 loop = impl_do ();
429 // Restore.
430 RESTORE_POS (1);
431 UNSCAN;
432 rc = scan ("(");
433 // Decide.
434 if (loop) {
435 (*nest)++;
436 int_4 where = code (nprocs, BODY, NO_TEXT);
437 io_list (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, where, nest, items);
438 } else {
439 io_elem (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, items);
440 rc = scan (EXPECT_NONE);
441 }
442 } else if (TOKEN (")")) {
443 // Expression closed by ')'
444 (*nest)--;
445 return;
446 } else if (rc == WORD) {
447 if (*nest == 0) {
448 io_elem (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, items);
449 rc = scan (EXPECT_NONE);
450 } else {
451 SAVE_POS (2);
452 rc = scan (EXPECT_NONE);
453 if (!TOKEN ("=")) {
454 RESTORE_POS (2);
455 UNSCAN;
456 rc = scan (EXPECT_NONE);
457 io_elem (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, items);
458 rc = scan (EXPECT_NONE);
459 } else {
460 NEW_RECORD (lid); NEW_RECORD (loop);
461 EXPR from, to, by;
462 MODE mode;
463 IDENT *idf = impl_decl (prelex, &mode);
464 if (idf->arg || idf->alias != NULL) {
465 _srecordf (lid, "*%s", C_NAME (idf));
466 } else {
467 (void) idf_full_c_name (lid, idf);
468 }
469 rc = scan (EXPECT_NONE);
470 express (&from, idf->mode.type, idf->mode.len);
471 rc = scan (",");
472 rc = scan (EXPECT_NONE);
473 express (&to, idf->mode.type, idf->mode.len);
474 rc = scan (EXPECT_NONE);
475 if (TOKEN (",")) {
476 rc = scan (EXPECT_NONE);
477 express (&by, idf->mode.type, idf->mode.len);
478 _srecordf (loop, "for (%s = %s; %s <= %s; %s += %s) {\n",
479 lid, from.str, lid, to.str, lid, by.str);
480 rc = scan (EXPECT_NONE);
481 } else {
482 _srecordf (loop, "for (%s = %s; %s <= %s; %s++) {\n",
483 lid, from.str, lid, to.str, lid);
484 }
485 patch (lpatch, loop);
486 if (TOKEN (")")) {
487 // Implied DO loop closed by ')'.
488 (*nest)--;
489 code (nprocs, BODY, "}; // implied DO \n");
490 } else {
491 EXPECT (3304, ")");
492 }
493 return;
494 }
495 }
496 } else {
497 io_elem (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, items);
498 rc = scan (EXPECT_NONE);
499 }
500 }
501 }
502
503 void io_unit (EXPR *unit, int_4 defunit)
504 {
505 // Reasonable default.
506 unit->mode.type = INTEGER;
507 unit->mode.len = 4;
508 //
509 if (TOKEN ("*")) {
510 _srecordf (unit->str, "%d", defunit);
511 } else if (TOKEN ("stdin")) {
512 _srecordf (unit->str, "STDF_IN");
513 } else if (TOKEN ("stdout")) {
514 _srecordf (unit->str, "STDF_OUT");
515 } else if (TOKEN ("stderr")) {
516 _srecordf (unit->str, "STDF_ERR");
517 } else {
518 EXPR reg;
519 express (®, NOTYPE, NOLEN);
520 if (reg.mode.type == INTEGER) {
521 if (reg.variant == EXPR_CONST) {
522 _srecordf (unit->str, "%s", reg.str);
523 int_4 val;
524 (void) is_int4 (unit->str, &val);
525 if (val < 1 || val > MAX_FILES - 1) {
526 ERROR (3305, "unit number out of range", unit->str);
527 }
528 } else {
529 NEW_RECORD (str);
530 _srecordf (unit->str, "%s", edit_unit (nloctmps++));
531 add_local (unit->str, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
532 _srecordf (str, "%s = %s;\n", unit, reg.str);
533 code (nprocs, BODY, str);
534 }
535 } else if (reg.mode.type == CHARACTER) {
536 (*unit) = reg;
537 } else {
538 ERROR (3306, "unit must be INTEGER or CHARACTER", NO_TEXT);
539 }
540 }
541 }
542
543 static void io_specs (char *proc, EXPR *unit, int_4 defunit, EXPR *rec, EXPR *fmt, char **fn, char **form, char **action, int_4 *lrecl, char **disp, LBL **end, LBL **err, char **iostat)
544 {
545 int_4 rc, parm = 1;
546 RECCLR (unit->str);
547 RECCLR (rec->str);
548 RECCLR (fmt->str);
549 *action = action_default;
550 *disp = disp_old;
551 *end = NO_LABEL;
552 *err = NO_LABEL;
553 *fn = NO_TEXT;
554 *form = form_unformatted;
555 *iostat = NO_TEXT;
556 rec->str[0] = '\0';
557 // We accept that only a unit specification follows.
558 if (curret == INT_NUMBER || curret == WORD) {
559 io_unit (unit, defunit);
560 return;
561 }
562 if (TOKEN ("(")) {
563 rc = scan (EXPECT_NONE);
564 } else {
565 EXPECT (3307, "(");
566 return;
567 }
568 //
569 while (!TOKEN (")") && rc != END_OF_MODULE) {
570 // ([UNIT], [FMT] [, FMT=n | FILE=expr | FORM=str | action=str | DISP=str | END=n | ERR=n])
571 if (TOKEN ("unit") && lookahead ("=")) {
572 rc = scan ("=");
573 rc = scan (EXPECT_NONE);
574 io_unit (unit, defunit);
575 } else if (TOKEN ("rec") && lookahead ("=")) {
576 rc = scan ("=");
577 rc = scan (EXPECT_NONE);
578 express (rec, INTEGER, 4);
579 } else if (TOKEN ("file") && lookahead ("=")) {
580 EXPR reg;
581 rc = scan ("=");
582 rc = scan (EXPECT_NONE);
583 if (express (®, CHARACTER, NOLEN)) {
584 *fn = f_stralloc (reg.str);
585 }
586 } else if (TOKEN ("form") && lookahead ("=")) {
587 rc = scan ("=");
588 rc = scan (EXPECT_NONE);
589 if (MATCH ("formatted")) {
590 *form = form_formatted;
591 } else if (MATCH ("unformatted")) {
592 *form = form_unformatted;
593 } else {
594 SYNTAX (3308, "invalid FORM specification");
595 }
596 } else if ((TOKEN ("action") || TOKEN ("access")) && lookahead ("=")) {
597 rc = scan ("=");
598 rc = scan (EXPECT_NONE);
599 if (MATCH ("read")) {
600 *action = action_read;
601 } else if (MATCH ("write")) {
602 *action = action_write;
603 } else if (MATCH ("readwrite")) {
604 *action = action_readwrite;
605 } else if (MATCH ("direct")) {
606 *action = action_readwrite;
607 } else {
608 SYNTAX (3309, "invalid ACCESS specification");
609 }
610 } else if ((TOKEN ("disp") || TOKEN ("status")) && lookahead ("=")) {
611 // Straight from JCL :-)
612 rc = scan ("=");
613 rc = scan (EXPECT_NONE);
614 if (MATCH ("old")) {
615 *disp = disp_old;
616 } else if (MATCH ("new")) {
617 *disp = disp_new;
618 } else if (MATCH ("keep")) {
619 *disp = disp_keep;
620 } else if (MATCH ("delete")) {
621 *disp = disp_delete;
622 } else if (MATCH ("unknown")) {
623 *disp = disp_new;
624 } else {
625 SYNTAX (3310, "invalid DISP specification");
626 }
627 } else if ((TOKEN ("lrecl") || TOKEN ("recl")) && lookahead ("=")) {
628 rc = scan ("=");
629 rc = scan (EXPECT_NONE);
630 express (rec, INTEGER, 4);
631 } else if (TOKEN ("fmt") && lookahead ("=")) {
632 rc = scan ("=");
633 rc = scan (EXPECT_NONE);
634 if (TOKEN ("*")) {
635 *form = form_formatted;
636 } else if (rc == INT_NUMBER) {
637 bufcpy (fmt->str, curlex, RECLN);
638 fmt->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
639 *form = form_formatted;
640 } else if (rc == WORD) {
641 express (fmt, NOTYPE, NOLEN);
642 *form = form_formatted;
643 } else if (rc == TEXT) {
644 int_4 k = format_str (curlex);
645 _srecordf (fmt->str, "%d", k);
646 fmt->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
647 *form = form_formatted;
648 } else {
649 EXPECT (3311, "label or format string");
650 }
651 } else if (TOKEN ("end") && lookahead ("=")) {
652 rc = scan ("=");
653 if ((rc = scan (EXPECT_LABEL)) == LABEL) {
654 if (((*end) = find_label (curlex)) == NO_LABEL) {
655 ERROR (3312, "no such label", curlex);
656 }
657 (*end)->jumped++;
658 } else {
659 EXPECT (3313, "label");
660 }
661 } else if (TOKEN ("err") && lookahead ("=")) {
662 rc = scan ("=");
663 if ((rc = scan (EXPECT_LABEL)) == LABEL) {
664 if (((*err) = find_label (curlex)) == NO_LABEL) {
665 ERROR (3314, "no such label", curlex);
666 }
667 (*err)->jumped++;
668 } else {
669 EXPECT (3315, "label");
670 }
671 } else if (TOKEN ("iostat") && lookahead ("=")) {
672 rc = scan ("=");
673 rc = scan (EXPECT_NONE);
674 if (rc != WORD) {
675 EXPECT (3316, "variable")
676 } else {
677 (void) impl_decl (curlex, NO_MODE);
678 *iostat = f_stralloc (curlex);
679 }
680 } else {
681 if (EQUAL (proc, "encode") || EQUAL (proc, "decode")) {
682 if (parm == 1 && rc == INT_NUMBER) {
683 (void) is_int4 (curlex, lrecl);
684 } else if (parm == 2 && TOKEN ("*")) {
685 ;
686 } else if (parm == 2 && rc == WORD) {
687 express (fmt, NOTYPE, NOLEN);
688 *form = form_formatted;
689 } else if (parm == 2 && rc == TEXT) {
690 int_4 k = format_str (curlex);
691 _srecordf (fmt->str, "%d", k);
692 fmt->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
693 } else if (parm == 2 && rc == INT_NUMBER) {
694 bufcpy (fmt->str, curlex, RECLN);
695 fmt->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
696 } else if (parm == 3) {
697 io_unit (unit, defunit);
698 } else {
699 SYNTAX (3317, curlex);
700 }
701 } else {
702 if (parm == 1) {
703 io_unit (unit, defunit);
704 } else if (parm == 2 && TOKEN ("*")) {
705 *form = form_formatted;
706 } else if (parm == 2 && rc == WORD) {
707 express (fmt, NOTYPE, NOLEN);
708 *form = form_formatted;
709 } else if (parm == 2 && rc == TEXT) {
710 int_4 k = format_str (curlex);
711 _srecordf (fmt->str, "%d", k);
712 fmt->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
713 *form = form_formatted;
714 } else if (parm == 2 && rc == INT_NUMBER) {
715 bufcpy (fmt->str, curlex, RECLN);
716 fmt->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
717 *form = form_formatted;
718 } else {
719 SYNTAX (3318, curlex);
720 }
721 }
722 }
723 // Next item.
724 parm++;
725 rc = scan (EXPECT_NONE);
726 if (TOKEN (",")) {
727 rc = scan (EXPECT_NONE);
728 } else if (TOKEN (")")) {
729 ;
730 } else {
731 SYNTAX (3319, curlex);
732 }
733 }
734 }
735
736 void vif_close (void)
737 {
738 int_4 rc, lrecl = 0;
739 char *daction = NO_TEXT, *ddisp = NO_TEXT, *dfn = NO_TEXT, *dform = NO_TEXT, *iostat = NO_TEXT;
740 EXPR unit, rec, fmt;
741 LBL *endlbl = NO_LABEL, *errlbl = NO_LABEL;
742 NEW_RECORD (str);
743 rc = scan (EXPECT_NONE);
744 io_specs ("close", &unit, ERR, &rec, &fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
745 _srecordf (str, "_fcheck (\"%s\", %s, NULL, NULL);\n", stat_start, unum (&unit));
746 code (nprocs, BODY, str);
747 _srecordf (str, "if (_ffile[%s].unit != NULL) {\n", unum (&unit));
748 code (nprocs, BODY, str);
749 _srecordf (str, "_funregister (\"%s\", %s);\n", stat_start, unum (&unit));
750 code (nprocs, BODY, str);
751 if (iostat != NO_TEXT) {
752 NEW_RECORD (ios);
753 _srecordf (ios, "%s_ = errno;\n", iostat);
754 code (nprocs, BODY, ios);
755 }
756 code (nprocs, BODY, "if (errno != 0) {\n");
757 if (errlbl == NO_LABEL) {
758 _srecordf (str, "_ioerr (\"%s\", %s);\n", stat_start, unum (&unit));
759 } else {
760 _srecordf (str, "goto _l%d;\n", errlbl->num);
761 }
762 code (nprocs, BODY, str);
763 code (nprocs, BODY, "}\n");
764 code (nprocs, BODY, "}\n");
765 (void) rc;
766 }
767
768 void vif_endfile (void)
769 {
770 int_4 rc, lrecl = 0;
771 char *daction = NO_TEXT, *ddisp = NO_TEXT, *dfn = NO_TEXT, *dform = NO_TEXT, *iostat = NO_TEXT;
772 EXPR unit, rec, fmt;
773 LBL *endlbl = NO_LABEL, *errlbl = NO_LABEL;
774 NEW_RECORD (str);
775 rc = scan (EXPECT_NONE);
776 io_specs ("endfile", &unit, ERR, &rec, &fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
777 _srecordf (str, "_fcheck (\"%s\", %s, NULL, NULL);\n", stat_start, unum (&unit));
778 code (nprocs, BODY, str);
779 _srecordf (str, "if (_ffile[%s].unit != NULL) {\n", unum (&unit));
780 code (nprocs, BODY, str);
781 _srecordf (str, "fprintf (_ffile[%s].unit, \"%%c\", EOF);\n", unum (&unit));
782 code (nprocs, BODY, str);
783 if (iostat != NO_TEXT) {
784 NEW_RECORD (ios);
785 _srecordf (ios, "%s_ = errno;\n", iostat);
786 code (nprocs, BODY, ios);
787 }
788 code (nprocs, BODY, "if (errno != 0) {\n");
789 if (errlbl == NO_LABEL) {
790 _srecordf (str, "_ioerr (\"%s\", %s);\n", stat_start, unum (&unit));
791 } else {
792 _srecordf (str, "goto _l%d;\n", errlbl->num);
793 }
794 code (nprocs, BODY, str);
795 code (nprocs, BODY, "}\n");
796 code (nprocs, BODY, "}\n");
797 (void) rc;
798 }
799
800 void vif_backspace (void)
801 {
802 int_4 rc, lrecl = 0;
803 char *daction = NO_TEXT, *ddisp = NO_TEXT, *dfn = NO_TEXT, *dform = NO_TEXT, *iostat = NO_TEXT;
804 EXPR unit, rec, fmt;
805 LBL *endlbl = NO_LABEL, *errlbl = NO_LABEL;
806 NEW_RECORD (str);
807 rc = scan (EXPECT_NONE);
808 io_specs ("backspace", &unit, ERR, &rec, &fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
809 _srecordf (str, "_fcheck (\"%s\", %s, NULL, NULL);\n", stat_start, unum (&unit));
810 code (nprocs, BODY, str);
811 _srecordf (str, "if (_ffile[%s].unit != NULL) {\n", unum (&unit));
812 code (nprocs, BODY, str);
813 _srecordf (str, "_backspace (\"%s\", %s);\n", stat_start, unum (&unit));
814 code (nprocs, BODY, str);
815 if (iostat != NO_TEXT) {
816 NEW_RECORD (ios);
817 _srecordf (ios, "%s_ = errno;\n", iostat);
818 code (nprocs, BODY, ios);
819 }
820 code (nprocs, BODY, "if (errno != 0) {\n");
821 if (errlbl == NO_LABEL) {
822 _srecordf (str, "_ioerr (\"%s\", %s);\n", stat_start, unum (&unit));
823 } else {
824 _srecordf (str, "goto _l%d;\n", errlbl->num);
825 }
826 code (nprocs, BODY, str);
827 code (nprocs, BODY, "}\n");
828 code (nprocs, BODY, "}\n");
829 (void) rc;
830 }
831
832 void vif_rewind (void)
833 {
834 int_4 rc, lrecl = 0;
835 char *daction = NO_TEXT, *ddisp = NO_TEXT, *dfn = NO_TEXT, *dform = NO_TEXT, *iostat = NO_TEXT;
836 EXPR unit, rec, fmt;
837 LBL *endlbl = NO_LABEL, *errlbl = NO_LABEL;
838 NEW_RECORD (str);
839 rc = scan (EXPECT_NONE);
840 io_specs ("rewind", &unit, ERR, &rec, &fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
841 _srecordf (str, "_fcheck (\"%s\", %s, NULL, NULL);\n", stat_start, unum (&unit));
842 code (nprocs, BODY, str);
843 _srecordf (str, "if (_ffile[%s].unit != NULL) {\n", unum (&unit));
844 code (nprocs, BODY, str);
845 _srecordf (str, "_rewind (\"%s\", %s);\n", stat_start, unum (&unit));
846 code (nprocs, BODY, str);
847 if (iostat != NO_TEXT) {
848 NEW_RECORD (ios);
849 _srecordf (ios, "%s_ = errno;\n", iostat);
850 code (nprocs, BODY, ios);
851 }
852 code (nprocs, BODY, "if (errno != 0) {\n");
853 if (errlbl == NO_LABEL) {
854 _srecordf (str, "_ioerr (\"%s\", %s);\n", stat_start, unum (&unit));
855 } else {
856 _srecordf (str, "goto _l%d;\n", errlbl->num);
857 }
858 code (nprocs, BODY, str);
859 code (nprocs, BODY, "}\n");
860 code (nprocs, BODY, "}\n");
861 (void) rc;
862 }
863
864 void vif_open (void)
865 {
866 int_4 rc, lrecl = 0;
867 char *daction = NO_TEXT, *dfn = NO_TEXT, *dform = NO_TEXT, *ddisp = NO_TEXT, *iostat = NO_TEXT;
868 LBL *endlbl = NO_LABEL, *errlbl = NO_LABEL;
869 EXPR unit, rec, fmt;
870 NEW_RECORD (str);
871 rc = scan (EXPECT_NONE);
872 io_specs ("open", &unit, ERR, &rec, &fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
873 if (dfn != NO_TEXT) {
874 _srecordf (str, "_fregister (\"%s\", %s, %d, %s, %s, %s, %s);\n", stat_start, unum (&unit), lrecl, dfn, dform, daction, ddisp);
875 } else {
876 _srecordf (str, "_fregister (\"%s\", %s, %d, NULL, %s, %s, %s);\n", stat_start, unum (&unit), lrecl, dform, daction, ddisp);
877 }
878 code (nprocs, BODY, str);
879 if (iostat != NO_TEXT) {
880 NEW_RECORD (ios);
881 _srecordf (ios, "%s_ = errno;\n", iostat);
882 code (nprocs, BODY, ios);
883 }
884 (void) rc;
885 }
886
887 void io_open_internal (EXPR *unit, char *acc)
888 {
889 if (unit->mode.type != CHARACTER) {
890 ERROR (3320, "unit type must be CHARACTER", unit->str);
891 } else if (unit->variant == EXPR_CONST) {
892 ERROR (3321, "unit must be CHARACTER variable", unit->str);
893 } else {
894 int N = unit->mode.len, M = 1;
895 if (unit->idf->mode.dim == 0) {
896 ;
897 } else {
898 NEW_RECORD (len);
899 compute_row_size (len, unit->idf);
900 if (! is_int4 (len, &M)) {
901 ERROR (3322, "size must be integer constant", len);
902 }
903 if (M > 1) {
904 N *= M;
905 }
906 }
907 NEW_RECORD (str);
908 _srecordf (str, "_ffile[0].buff = _ffile[0].rewind = (char *) (%s);\n", unit->str);
909 code (nprocs, BODY, str);
910 _srecordf (str, "_ffile[0].lrecl = %d;\n", unit->mode.len);
911 code (nprocs, BODY, str);
912 _srecordf (str, "_ffile[0].record = 0;\n");
913 code (nprocs, BODY, str);
914 _srecordf (str, "_ffile[0].records = %d;\n", M);
915 code (nprocs, BODY, str);
916 _srecordf (str, "_ffile[0].unit = fmemopen (%s, %d, \"%s\");\n", unit->str, N, acc);
917 code (nprocs, BODY, str);
918 _srecordf (str, "_ffile[0].buff_init = FALSE;\n");
919 code (nprocs, BODY, str);
920 }
921 }
922
923 void do_io (char *proc, int_4 *nest)
924 {
925 int_4 form = UNFORMATTED, lrecl = 0;
926 LBL *endlbl = NO_LABEL, *errlbl = NO_LABEL;
927 NEW_RECORD (fstr);
928 NEW_RECORD (fid);
929 NEW_RECORD (iorc);
930 NEW_RECORD (str);
931 char *daction = NO_TEXT, *ddisp = NO_TEXT, *dfn = NO_TEXT, *dform = NO_TEXT, *iostat = NO_TEXT;
932 EXPR unit, rec, fmt;
933 RECCLR (fmt.str);
934 unit.mode.type = INTEGER;
935 unit.mode.len = 4;
936 fstr[0] = '\0';
937 fid[0] = '\0';
938 iorc[0] = '\0';
939 rec.str[0] = '\0';
940 int_4 rc = scan (EXPECT_NONE);
941 if (EQUAL (proc, "read") || EQUAL (proc, "accept")) {
942 if (TOKEN ("*")) {
943 _srecordf (unit.str, "STDF_IN");
944 dform = form_formatted;
945 rc = scan (EXPECT_NONE);
946 } else if (rc == INT_NUMBER) { // FORTRAN II
947 _srecordf (unit.str, "STDF_IN");
948 bufcpy (fmt.str, curlex, RECLN);
949 fmt.mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
950 dform = form_formatted;
951 rc = scan (EXPECT_NONE);
952 } else if (rc == TEXT) {
953 _srecordf (unit.str, "STDF_IN");
954 int_4 k = format_str (curlex);
955 _srecordf (fmt.str, "%d", k);
956 fmt.mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
957 dform = form_formatted;
958 rc = scan (EXPECT_NONE);
959 } else {
960 io_specs (proc, &unit, STDF_IN, &rec, &fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
961 }
962 } else if (EQUAL (proc, "write") || EQUAL (proc, "print") || EQUAL (proc, "punch")) {
963 if (TOKEN ("*")) {
964 _srecordf (unit.str, "STDF_OUT");
965 dform = form_formatted;
966 rc = scan (EXPECT_NONE);
967 } else if (rc == INT_NUMBER) { // FORTRAN II
968 _srecordf (unit.str, "STDF_OUT");
969 bufcpy (fmt.str, curlex, RECLN);
970 fmt.mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
971 dform = form_formatted;
972 rc = scan (EXPECT_NONE);
973 } else if (rc == TEXT) {
974 _srecordf (unit.str, "STDF_OUT");
975 int_4 k = format_str (curlex);
976 _srecordf (fmt.str, "%d", k);
977 fmt.mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
978 dform = form_formatted;
979 rc = scan (EXPECT_NONE);
980 } else {
981 io_specs (proc, &unit, STDF_OUT, &rec, &fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
982 }
983 } else if (EQUAL (proc, "encode") || EQUAL (proc, "decode")) {
984 io_specs (proc, &unit, STDF_OUT, &rec, &fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
985 ddisp = disp_old;
986 dfn = NO_TEXT;
987 iostat = NO_TEXT;
988 dform = form_formatted;
989 if (EQUAL (proc, "encode")) {
990 proc = "write";
991 daction = action_write;
992 } else if (EQUAL (proc, "decode")) {
993 proc = "read";
994 daction = action_read;
995 }
996 }
997 if (strlen (fmt.str) == 0 && dform != form_unformatted) {
998 form = STDFORMAT;
999 } else if (strlen (fmt.str) == 0 && dform == form_unformatted) {
1000 form = UNFORMATTED;
1001 } else {
1002 form = FORMATTED;
1003 }
1004 // IO to a string implies UNIT=0.
1005 if (unit.mode.type == CHARACTER) {
1006 if (EQUAL (proc, "read")) {
1007 io_open_internal (&unit, "r");
1008 } else if (EQUAL (proc, "accept")) {
1009 io_open_internal (&unit, "r");
1010 } else if (EQUAL (proc, "write")) {
1011 io_open_internal (&unit, "w");
1012 } else if (EQUAL (proc, "print")) {
1013 io_open_internal (&unit, "w");
1014 } else if (EQUAL (proc, "punch")) {
1015 io_open_internal (&unit, "w");
1016 }
1017 }
1018 // Runtime checks - can the file do this?
1019 if (EQUAL (proc, "read")) {
1020 _srecordf (str, "_fcheck (\"%s\", %s, action_read, %s);\n", stat_start, unum (&unit), dform);
1021 } else if (EQUAL (proc, "accept")) {
1022 _srecordf (str, "_fcheck (\"%s\", %s, action_read, %s);\n", stat_start, unum (&unit), dform);
1023 } else if (EQUAL (proc, "write")) {
1024 _srecordf (str, "_fcheck (\"%s\", %s, action_write, %s);\n", stat_start, unum (&unit), dform);
1025 } else if (EQUAL (proc, "print")) {
1026 _srecordf (str, "_fcheck (\"%s\", %s, action_write, %s);\n", stat_start, unum (&unit), dform);
1027 } else if (EQUAL (proc, "punch")) {
1028 _srecordf (str, "_fcheck (\"%s\", %s, action_write, %s);\n", stat_start, unum (&unit), dform);
1029 }
1030 code (nprocs, BODY, str);
1031 // Set record.
1032 if (strlen (rec.str) > 0) {
1033 _srecordf (str, "_set_record (\"%s\", %s, %s);\n", stat_start, unum (&unit), rec.str);
1034 code (nprocs, BODY, str);
1035 }
1036 // Formats.
1037 if (form == FORMATTED) {
1038 NEW_RECORD (fcnt);
1039 int_4 val;
1040 _srecordf (fid, "__fcnt");
1041 add_local (fid, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
1042 _srecordf (iorc, "__rc");
1043 add_local (iorc, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
1044 _srecordf (fcnt, "%s = 0;\n", fid);
1045 code (nprocs, BODY, fcnt);
1046 if (is_int4 (fmt.str, &val)) {
1047 _srecordf (fstr, "%s", edit_fmt (val));
1048 } else {
1049 if (fmt.mode.type == INTEGER) {
1050 // Assigned FORMAT.
1051 _srecordf (str, "switch (%s) {\n", fmt.str);
1052 code (nprocs, BODY, str);
1053 code (nprocs, BODY, "default:\n");
1054 for (int_4 k = 0; k < nlabels; k++) {
1055 LBL *L = &labels[k];
1056 if (L->format) {
1057 L->jumped++;
1058 _srecordf (str, "case %d: __fmt_a = %s; break;\n", L->index, edit_fmt(L->num));
1059 code (nprocs, BODY, str);
1060 }
1061 }
1062 code (nprocs, BODY, "}\n");
1063 RECCPY (fstr, "__fmt_a");
1064 } else if (fmt.mode.type == CHARACTER) {
1065 _srecordf (str, "__fmt_a = _vif_jit (\"%s\", %s);\n", stat_start, fmt.str);
1066 code (nprocs, BODY, str);
1067 RECCPY (fstr, "__fmt_a");
1068 } else {
1069 ERROR (3323, "format identifier mode error", qtype (&fmt.mode));
1070 }
1071 }
1072 } else {
1073 _srecordf (iorc, "__rc_%d", nloctmps++);
1074 add_local (iorc, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
1075 }
1076 // Start-of-record.
1077 if (form == FORMATTED) {
1078 if (EQUAL (proc, "read")) {
1079 io_text_items ("read", &unit, fstr, fid, iorc, endlbl, errlbl, FALSE);
1080 } else if (EQUAL (proc, "accept")) {
1081 io_text_items ("read", &unit, fstr, fid, iorc, endlbl, errlbl, FALSE);
1082 } else if (EQUAL (proc, "write")) {
1083 io_text_items ("write", &unit, fstr, fid, iorc, endlbl, errlbl, FALSE);
1084 } else if (EQUAL (proc, "print")) {
1085 io_text_items ("write", &unit, fstr, fid, iorc, endlbl, errlbl, FALSE);
1086 } else if (EQUAL (proc, "punch")) {
1087 io_text_items ("write", &unit, fstr, fid, iorc, endlbl, errlbl, FALSE);
1088 }
1089 }
1090 int_4 items = 0;
1091 if (EQUAL (proc, "read")) {
1092 io_list ("read", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
1093 } else if (EQUAL (proc, "accept")) {
1094 io_list ("read", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
1095 } else if (EQUAL (proc, "write")) {
1096 io_list ("write", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
1097 } else if (EQUAL (proc, "print")) {
1098 io_list ("write", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
1099 } else if (EQUAL (proc, "punch")) {
1100 io_list ("write", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
1101 }
1102 if (unit.mode.type == CHARACTER) {
1103 // IO to a string implies UNIT=0.
1104 // code (nprocs, BODY, "_fclose (0);\n");
1105 } else if (EQUAL (proc, "write") || EQUAL (proc, "print") || EQUAL (proc, "punch")) {
1106 // End-of-record.
1107 if (form != UNFORMATTED) {
1108 _srecordf (str, "_write_eol (%s);\n", unum (&unit));
1109 code (nprocs, BODY, str);
1110 }
1111 } else if (EQUAL (proc, "read") || EQUAL (proc, "accept")) {
1112 // End-of-record.
1113 if (form != UNFORMATTED) {
1114 _srecordf (str, "_read_eol (%s);\n", unum (&unit));
1115 code (nprocs, BODY, str);
1116 }
1117 }
1118 //
1119 save_iostat (iostat);
1120 //
1121 (void) rc;
1122 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|