]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/io/write.c
Update copyright years.
[thirdparty/gcc.git] / libgfortran / io / write.c
CommitLineData
7adcbafe 1/* Copyright (C) 2002-2022 Free Software Foundation, Inc.
6de9cd9a 2 Contributed by Andy Vaught
8b6dba81 3 Namelist output contributed by Paul Thomas
10256cbe 4 F2003 I/O support contributed by Jerry DeLisle
6de9cd9a 5
bb408e87 6This file is part of the GNU Fortran runtime library (libgfortran).
6de9cd9a
DN
7
8Libgfortran is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
748086b7 10the Free Software Foundation; either version 3, or (at your option)
6de9cd9a
DN
11any later version.
12
13Libgfortran is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
748086b7
JJ
18Under Section 7 of GPL version 3, you are granted additional
19permissions described in the GCC Runtime Library Exception, version
203.1, as published by the Free Software Foundation.
21
22You should have received a copy of the GNU General Public License and
23a copy of the GCC Runtime Library Exception along with this program;
24see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25<http://www.gnu.org/licenses/>. */
6de9cd9a 26
36ae8a61 27#include "io.h"
1060d940 28#include "fbuf.h"
92cbdb68
JB
29#include "format.h"
30#include "unix.h"
1449b8cb 31#include <assert.h>
6de9cd9a 32#include <string.h>
887d9b8b 33
6de9cd9a
DN
34#define star_fill(p, n) memset(p, '*', n)
35
3ae86bf4
JD
36typedef unsigned char uchar;
37
c7421e06
JD
38/* Helper functions for character(kind=4) internal units. These are needed
39 by write_float.def. */
40
992b0aa1 41static void
746e6327 42memcpy4 (gfc_char4_t *dest, const char *source, int k)
c7421e06
JD
43{
44 int j;
e73d3ca6 45
c7421e06 46 const char *p = source;
c7421e06 47 for (j = 0; j < k; j++)
746e6327 48 *dest++ = (gfc_char4_t) *p++;
c7421e06
JD
49}
50
51/* This include contains the heart and soul of formatted floating point. */
52#include "write_float.def"
53
3ae86bf4
JD
54/* Write out default char4. */
55
56static void
5609699a 57write_default_char4 (st_parameter_dt *dtp, const gfc_char4_t *source,
3ae86bf4
JD
58 int src_len, int w_len)
59{
60 char *p;
61 int j, k = 0;
62 gfc_char4_t c;
63 uchar d;
e73d3ca6 64
3ae86bf4
JD
65 /* Take care of preceding blanks. */
66 if (w_len > src_len)
67 {
68 k = w_len - src_len;
69 p = write_block (dtp, k);
70 if (p == NULL)
71 return;
c7421e06 72 if (is_char4_unit (dtp))
746e6327
JD
73 {
74 gfc_char4_t *p4 = (gfc_char4_t *) p;
75 memset4 (p4, ' ', k);
76 }
c7421e06
JD
77 else
78 memset (p, ' ', k);
3ae86bf4
JD
79 }
80
81 /* Get ready to handle delimiters if needed. */
105b7136 82 switch (dtp->u.p.current_unit->delim_status)
3ae86bf4
JD
83 {
84 case DELIM_APOSTROPHE:
85 d = '\'';
86 break;
87 case DELIM_QUOTE:
88 d = '"';
89 break;
90 default:
91 d = ' ';
92 break;
93 }
94
95 /* Now process the remaining characters, one at a time. */
c7421e06 96 for (j = 0; j < src_len; j++)
3ae86bf4
JD
97 {
98 c = source[j];
c7421e06 99 if (is_char4_unit (dtp))
3ae86bf4 100 {
c7421e06
JD
101 gfc_char4_t *q;
102 /* Handle delimiters if any. */
103 if (c == d && d != ' ')
104 {
105 p = write_block (dtp, 2);
106 if (p == NULL)
107 return;
108 q = (gfc_char4_t *) p;
109 *q++ = c;
110 }
111 else
112 {
113 p = write_block (dtp, 1);
114 if (p == NULL)
115 return;
116 q = (gfc_char4_t *) p;
117 }
118 *q = c;
3ae86bf4
JD
119 }
120 else
121 {
c7421e06
JD
122 /* Handle delimiters if any. */
123 if (c == d && d != ' ')
124 {
125 p = write_block (dtp, 2);
126 if (p == NULL)
127 return;
128 *p++ = (uchar) c;
129 }
130 else
131 {
132 p = write_block (dtp, 1);
133 if (p == NULL)
134 return;
135 }
136 *p = c > 255 ? '?' : (uchar) c;
3ae86bf4 137 }
3ae86bf4
JD
138 }
139}
140
141
142/* Write out UTF-8 converted from char4. */
143
144static void
145write_utf8_char4 (st_parameter_dt *dtp, gfc_char4_t *source,
146 int src_len, int w_len)
147{
148 char *p;
149 int j, k = 0;
150 gfc_char4_t c;
151 static const uchar masks[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
152 static const uchar limits[6] = { 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
7812c78c 153 int nbytes;
e73d3ca6 154 uchar buf[6], d, *q;
3ae86bf4
JD
155
156 /* Take care of preceding blanks. */
157 if (w_len > src_len)
158 {
159 k = w_len - src_len;
160 p = write_block (dtp, k);
161 if (p == NULL)
162 return;
163 memset (p, ' ', k);
164 }
165
166 /* Get ready to handle delimiters if needed. */
105b7136 167 switch (dtp->u.p.current_unit->delim_status)
3ae86bf4
JD
168 {
169 case DELIM_APOSTROPHE:
170 d = '\'';
171 break;
172 case DELIM_QUOTE:
173 d = '"';
174 break;
175 default:
176 d = ' ';
177 break;
178 }
179
180 /* Now process the remaining characters, one at a time. */
181 for (j = k; j < src_len; j++)
182 {
183 c = source[j];
184 if (c < 0x80)
185 {
186 /* Handle the delimiters if any. */
187 if (c == d && d != ' ')
188 {
189 p = write_block (dtp, 2);
190 if (p == NULL)
191 return;
192 *p++ = (uchar) c;
193 }
194 else
195 {
196 p = write_block (dtp, 1);
197 if (p == NULL)
198 return;
199 }
200 *p = (uchar) c;
201 }
202 else
203 {
204 /* Convert to UTF-8 sequence. */
205 nbytes = 1;
206 q = &buf[6];
207
208 do
209 {
210 *--q = ((c & 0x3F) | 0x80);
211 c >>= 6;
212 nbytes++;
213 }
214 while (c >= 0x3F || (c & limits[nbytes-1]));
215
216 *--q = (c | masks[nbytes-1]);
217
218 p = write_block (dtp, nbytes);
219 if (p == NULL)
220 return;
221
222 while (q < &buf[6])
223 *p++ = *q++;
224 }
225 }
226}
227
228
0ef33d44
FR
229/* Check the first character in source if we are using CC_FORTRAN
230 and set the cc.type appropriately. The cc.type is used later by write_cc
231 to determine the output start-of-record, and next_record_cc to determine the
232 output end-of-record.
233 This function is called before the output buffer is allocated, so alloc_len
234 is set to the appropriate size to allocate. */
235
236static void
ea99ec5b 237write_check_cc (st_parameter_dt *dtp, const char **source, size_t *alloc_len)
0ef33d44
FR
238{
239 /* Only valid for CARRIAGECONTROL=FORTRAN. */
240 if (dtp->u.p.current_unit->flags.cc != CC_FORTRAN
241 || alloc_len == NULL || source == NULL)
242 return;
243
244 /* Peek at the first character. */
245 int c = (*alloc_len > 0) ? (*source)[0] : EOF;
246 if (c != EOF)
247 {
248 /* The start-of-record character which will be printed. */
249 dtp->u.p.cc.u.start = '\n';
250 /* The number of characters to print at the start-of-record.
251 len > 1 means copy the SOR character multiple times.
252 len == 0 means no SOR will be output. */
253 dtp->u.p.cc.len = 1;
254
255 switch (c)
256 {
257 case '+':
258 dtp->u.p.cc.type = CCF_OVERPRINT;
259 dtp->u.p.cc.len = 0;
260 break;
261 case '-':
262 dtp->u.p.cc.type = CCF_ONE_LF;
263 dtp->u.p.cc.len = 1;
264 break;
265 case '0':
266 dtp->u.p.cc.type = CCF_TWO_LF;
267 dtp->u.p.cc.len = 2;
268 break;
269 case '1':
270 dtp->u.p.cc.type = CCF_PAGE_FEED;
271 dtp->u.p.cc.len = 1;
272 dtp->u.p.cc.u.start = '\f';
273 break;
274 case '$':
275 dtp->u.p.cc.type = CCF_PROMPT;
276 dtp->u.p.cc.len = 1;
277 break;
278 case '\0':
279 dtp->u.p.cc.type = CCF_OVERPRINT_NOA;
280 dtp->u.p.cc.len = 0;
281 break;
282 default:
283 /* In the default case we copy ONE_LF. */
284 dtp->u.p.cc.type = CCF_DEFAULT;
285 dtp->u.p.cc.len = 1;
286 break;
287 }
288
289 /* We add n-1 to alloc_len so our write buffer is the right size.
290 We are replacing the first character, and possibly prepending some
291 additional characters. Note for n==0, we actually subtract one from
292 alloc_len, which is correct, since that character is skipped. */
293 if (*alloc_len > 0)
294 {
295 *source += 1;
296 *alloc_len += dtp->u.p.cc.len - 1;
297 }
298 /* If we have no input, there is no first character to replace. Make
299 sure we still allocate enough space for the start-of-record string. */
300 else
301 *alloc_len = dtp->u.p.cc.len;
302 }
303}
304
305
306/* Write the start-of-record character(s) for CC_FORTRAN.
307 Also adjusts the 'cc' struct to contain the end-of-record character
308 for next_record_cc.
309 The source_len is set to the remaining length to copy from the source,
310 after the start-of-record string was inserted. */
311
312static char *
ea99ec5b 313write_cc (st_parameter_dt *dtp, char *p, size_t *source_len)
0ef33d44
FR
314{
315 /* Only valid for CARRIAGECONTROL=FORTRAN. */
316 if (dtp->u.p.current_unit->flags.cc != CC_FORTRAN || source_len == NULL)
317 return p;
318
319 /* Write the start-of-record string to the output buffer. Note that len is
320 never more than 2. */
321 if (dtp->u.p.cc.len > 0)
322 {
323 *(p++) = dtp->u.p.cc.u.start;
324 if (dtp->u.p.cc.len > 1)
325 *(p++) = dtp->u.p.cc.u.start;
326
327 /* source_len comes from write_check_cc where it is set to the full
328 allocated length of the output buffer. Therefore we subtract off the
329 length of the SOR string to obtain the remaining source length. */
330 *source_len -= dtp->u.p.cc.len;
331 }
332
333 /* Common case. */
334 dtp->u.p.cc.len = 1;
335 dtp->u.p.cc.u.end = '\r';
336
337 /* Update end-of-record character for next_record_w. */
338 switch (dtp->u.p.cc.type)
339 {
340 case CCF_PROMPT:
341 case CCF_OVERPRINT_NOA:
342 /* No end-of-record. */
343 dtp->u.p.cc.len = 0;
344 dtp->u.p.cc.u.end = '\0';
345 break;
346 case CCF_OVERPRINT:
347 case CCF_ONE_LF:
348 case CCF_TWO_LF:
349 case CCF_PAGE_FEED:
350 case CCF_DEFAULT:
351 default:
352 /* Carriage return. */
353 dtp->u.p.cc.len = 1;
354 dtp->u.p.cc.u.end = '\r';
355 break;
356 }
357
358 return p;
359}
360
6de9cd9a 361void
ea99ec5b
JB
362
363write_a (st_parameter_dt *dtp, const fnode *f, const char *source, size_t len)
6de9cd9a 364{
ea99ec5b 365 size_t wlen;
6de9cd9a
DN
366 char *p;
367
9355110f
JD
368 wlen = f->u.string.length < 0
369 || (f->format == FMT_G && f->u.string.length == 0)
ea99ec5b 370 ? len : (size_t) f->u.string.length;
6de9cd9a 371
9e7fc6b9
JD
372#ifdef HAVE_CRLF
373 /* If this is formatted STREAM IO convert any embedded line feed characters
374 to CR_LF on systems that use that sequence for newlines. See F2003
375 Standard sections 10.6.3 and 9.9 for further information. */
376 if (is_stream_io (dtp))
377 {
378 const char crlf[] = "\r\n";
ea99ec5b 379 size_t q, bytes;
9e7fc6b9
JD
380 q = bytes = 0;
381
382 /* Write out any padding if needed. */
383 if (len < wlen)
384 {
385 p = write_block (dtp, wlen - len);
386 if (p == NULL)
387 return;
388 memset (p, ' ', wlen - len);
389 }
390
391 /* Scan the source string looking for '\n' and convert it if found. */
ea99ec5b 392 for (size_t i = 0; i < wlen; i++)
9e7fc6b9
JD
393 {
394 if (source[i] == '\n')
395 {
396 /* Write out the previously scanned characters in the string. */
397 if (bytes > 0)
398 {
399 p = write_block (dtp, bytes);
400 if (p == NULL)
401 return;
402 memcpy (p, &source[q], bytes);
403 q += bytes;
404 bytes = 0;
405 }
406
e73d3ca6 407 /* Write out the CR_LF sequence. */
9e7fc6b9
JD
408 q++;
409 p = write_block (dtp, 2);
410 if (p == NULL)
411 return;
412 memcpy (p, crlf, 2);
413 }
414 else
415 bytes++;
416 }
417
418 /* Write out any remaining bytes if no LF was found. */
419 if (bytes > 0)
420 {
421 p = write_block (dtp, bytes);
422 if (p == NULL)
423 return;
424 memcpy (p, &source[q], bytes);
425 }
426 }
6de9cd9a
DN
427 else
428 {
9e7fc6b9 429#endif
0ef33d44
FR
430 if (dtp->u.p.current_unit->flags.cc == CC_FORTRAN)
431 write_check_cc (dtp, &source, &wlen);
432
9e7fc6b9
JD
433 p = write_block (dtp, wlen);
434 if (p == NULL)
435 return;
436
0ef33d44
FR
437 if (dtp->u.p.current_unit->flags.cc == CC_FORTRAN)
438 p = write_cc (dtp, p, &wlen);
439
c7421e06
JD
440 if (unlikely (is_char4_unit (dtp)))
441 {
746e6327 442 gfc_char4_t *p4 = (gfc_char4_t *) p;
c7421e06 443 if (wlen < len)
746e6327 444 memcpy4 (p4, source, wlen);
c7421e06
JD
445 else
446 {
746e6327
JD
447 memset4 (p4, ' ', wlen - len);
448 memcpy4 (p4 + wlen - len, source, len);
c7421e06
JD
449 }
450 return;
451 }
452
9e7fc6b9
JD
453 if (wlen < len)
454 memcpy (p, source, wlen);
455 else
456 {
457 memset (p, ' ', wlen - len);
458 memcpy (p + wlen - len, source, len);
459 }
460#ifdef HAVE_CRLF
6de9cd9a 461 }
9e7fc6b9 462#endif
6de9cd9a
DN
463}
464
cea93abb
JD
465
466/* The primary difference between write_a_char4 and write_a is that we have to
3ae86bf4
JD
467 deal with writing from the first byte of the 4-byte character and pay
468 attention to the most significant bytes. For ENCODING="default" write the
469 lowest significant byte. If the 3 most significant bytes contain
470 non-zero values, emit a '?'. For ENCODING="utf-8", convert the UCS-32 value
471 to the UTF-8 encoded string before writing out. */
cea93abb
JD
472
473void
ea99ec5b 474write_a_char4 (st_parameter_dt *dtp, const fnode *f, const char *source, size_t len)
cea93abb 475{
ea99ec5b 476 size_t wlen;
cea93abb
JD
477 gfc_char4_t *q;
478
479 wlen = f->u.string.length < 0
480 || (f->format == FMT_G && f->u.string.length == 0)
ea99ec5b 481 ? len : (size_t) f->u.string.length;
cea93abb
JD
482
483 q = (gfc_char4_t *) source;
484#ifdef HAVE_CRLF
485 /* If this is formatted STREAM IO convert any embedded line feed characters
486 to CR_LF on systems that use that sequence for newlines. See F2003
487 Standard sections 10.6.3 and 9.9 for further information. */
488 if (is_stream_io (dtp))
489 {
b495ad7f 490 const gfc_char4_t crlf[] = {0x000d,0x000a};
ea99ec5b 491 size_t bytes;
cea93abb
JD
492 gfc_char4_t *qq;
493 bytes = 0;
494
495 /* Write out any padding if needed. */
496 if (len < wlen)
497 {
cfd648ca 498 char *p;
cea93abb
JD
499 p = write_block (dtp, wlen - len);
500 if (p == NULL)
501 return;
502 memset (p, ' ', wlen - len);
503 }
504
505 /* Scan the source string looking for '\n' and convert it if found. */
506 qq = (gfc_char4_t *) source;
ea99ec5b 507 for (size_t i = 0; i < wlen; i++)
cea93abb
JD
508 {
509 if (qq[i] == '\n')
510 {
511 /* Write out the previously scanned characters in the string. */
512 if (bytes > 0)
513 {
3ae86bf4
JD
514 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
515 write_utf8_char4 (dtp, q, bytes, 0);
516 else
517 write_default_char4 (dtp, q, bytes, 0);
cea93abb
JD
518 bytes = 0;
519 }
520
e73d3ca6 521 /* Write out the CR_LF sequence. */
3ae86bf4 522 write_default_char4 (dtp, crlf, 2, 0);
cea93abb
JD
523 }
524 else
525 bytes++;
526 }
527
528 /* Write out any remaining bytes if no LF was found. */
529 if (bytes > 0)
530 {
3ae86bf4
JD
531 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
532 write_utf8_char4 (dtp, q, bytes, 0);
533 else
534 write_default_char4 (dtp, q, bytes, 0);
cea93abb
JD
535 }
536 }
537 else
538 {
539#endif
3ae86bf4
JD
540 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
541 write_utf8_char4 (dtp, q, len, wlen);
cea93abb 542 else
3ae86bf4 543 write_default_char4 (dtp, q, len, wlen);
cea93abb
JD
544#ifdef HAVE_CRLF
545 }
546#endif
547}
548
549
32aa3bff 550static GFC_INTEGER_LARGEST
6de9cd9a
DN
551extract_int (const void *p, int len)
552{
32aa3bff 553 GFC_INTEGER_LARGEST i = 0;
6de9cd9a
DN
554
555 if (p == NULL)
556 return i;
557
558 switch (len)
559 {
560 case 1:
98cd8256
SE
561 {
562 GFC_INTEGER_1 tmp;
563 memcpy ((void *) &tmp, p, len);
564 i = tmp;
565 }
6de9cd9a
DN
566 break;
567 case 2:
98cd8256
SE
568 {
569 GFC_INTEGER_2 tmp;
570 memcpy ((void *) &tmp, p, len);
571 i = tmp;
572 }
6de9cd9a
DN
573 break;
574 case 4:
98cd8256
SE
575 {
576 GFC_INTEGER_4 tmp;
577 memcpy ((void *) &tmp, p, len);
578 i = tmp;
579 }
6de9cd9a
DN
580 break;
581 case 8:
98cd8256
SE
582 {
583 GFC_INTEGER_8 tmp;
584 memcpy ((void *) &tmp, p, len);
585 i = tmp;
586 }
32aa3bff
FXC
587 break;
588#ifdef HAVE_GFC_INTEGER_16
589 case 16:
98cd8256
SE
590 {
591 GFC_INTEGER_16 tmp;
592 memcpy ((void *) &tmp, p, len);
593 i = tmp;
594 }
6de9cd9a 595 break;
32aa3bff 596#endif
6de9cd9a 597 default:
5e805e44 598 internal_error (NULL, "bad integer kind");
6de9cd9a
DN
599 }
600
601 return i;
602}
603
999a06a0
TK
604static GFC_UINTEGER_LARGEST
605extract_uint (const void *p, int len)
606{
607 GFC_UINTEGER_LARGEST i = 0;
608
609 if (p == NULL)
610 return i;
611
612 switch (len)
613 {
614 case 1:
98cd8256
SE
615 {
616 GFC_INTEGER_1 tmp;
617 memcpy ((void *) &tmp, p, len);
618 i = (GFC_UINTEGER_1) tmp;
619 }
999a06a0
TK
620 break;
621 case 2:
98cd8256
SE
622 {
623 GFC_INTEGER_2 tmp;
624 memcpy ((void *) &tmp, p, len);
625 i = (GFC_UINTEGER_2) tmp;
626 }
999a06a0
TK
627 break;
628 case 4:
98cd8256
SE
629 {
630 GFC_INTEGER_4 tmp;
631 memcpy ((void *) &tmp, p, len);
632 i = (GFC_UINTEGER_4) tmp;
633 }
999a06a0
TK
634 break;
635 case 8:
98cd8256
SE
636 {
637 GFC_INTEGER_8 tmp;
638 memcpy ((void *) &tmp, p, len);
639 i = (GFC_UINTEGER_8) tmp;
640 }
999a06a0
TK
641 break;
642#ifdef HAVE_GFC_INTEGER_16
486024b1 643 case 10:
999a06a0 644 case 16:
98cd8256 645 {
486024b1 646 GFC_INTEGER_16 tmp = 0;
98cd8256
SE
647 memcpy ((void *) &tmp, p, len);
648 i = (GFC_UINTEGER_16) tmp;
649 }
999a06a0
TK
650 break;
651#endif
652 default:
5e805e44 653 internal_error (NULL, "bad integer kind");
999a06a0
TK
654 }
655
656 return i;
657}
658
7984a2f0 659
6de9cd9a 660void
5e805e44 661write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
6de9cd9a
DN
662{
663 char *p;
9355110f 664 int wlen;
32aa3bff 665 GFC_INTEGER_LARGEST n;
7fcb1804 666
9355110f 667 wlen = (f->format == FMT_G && f->u.w == 0) ? 1 : f->u.w;
e73d3ca6 668
9355110f 669 p = write_block (dtp, wlen);
6de9cd9a
DN
670 if (p == NULL)
671 return;
672
6de9cd9a 673 n = extract_int (source, len);
c7421e06
JD
674
675 if (unlikely (is_char4_unit (dtp)))
676 {
677 gfc_char4_t *p4 = (gfc_char4_t *) p;
746e6327 678 memset4 (p4, ' ', wlen -1);
c7421e06
JD
679 p4[wlen - 1] = (n) ? 'T' : 'F';
680 return;
681 }
682
683 memset (p, ' ', wlen -1);
9355110f 684 p[wlen - 1] = (n) ? 'T' : 'F';
6de9cd9a
DN
685}
686
6de9cd9a 687static void
88a8126a 688write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n, int len)
6de9cd9a 689{
6de9cd9a 690 int w, m, digits, nzero, nblank;
1449b8cb 691 char *p;
6de9cd9a
DN
692
693 w = f->u.integer.w;
694 m = f->u.integer.m;
695
7fcb1804 696 /* Special case: */
6de9cd9a
DN
697
698 if (m == 0 && n == 0)
699 {
700 if (w == 0)
701 w = 1;
702
5e805e44 703 p = write_block (dtp, w);
6de9cd9a
DN
704 if (p == NULL)
705 return;
c7421e06 706 if (unlikely (is_char4_unit (dtp)))
746e6327
JD
707 {
708 gfc_char4_t *p4 = (gfc_char4_t *) p;
709 memset4 (p4, ' ', w);
710 }
c7421e06
JD
711 else
712 memset (p, ' ', w);
6de9cd9a
DN
713 goto done;
714 }
715
6de9cd9a
DN
716 digits = strlen (q);
717
718 /* Select a width if none was specified. The idea here is to always
7fcb1804 719 print something. */
6de9cd9a 720
88a8126a
JB
721 if (w == DEFAULT_WIDTH)
722 w = default_width_for_integer (len);
723
6de9cd9a
DN
724 if (w == 0)
725 w = ((digits < m) ? m : digits);
726
5e805e44 727 p = write_block (dtp, w);
6de9cd9a
DN
728 if (p == NULL)
729 return;
730
731 nzero = 0;
732 if (digits < m)
733 nzero = m - digits;
734
7fcb1804 735 /* See if things will work. */
6de9cd9a
DN
736
737 nblank = w - (nzero + digits);
738
c7421e06
JD
739 if (unlikely (is_char4_unit (dtp)))
740 {
741 gfc_char4_t *p4 = (gfc_char4_t *) p;
742 if (nblank < 0)
743 {
746e6327 744 memset4 (p4, '*', w);
c7421e06
JD
745 return;
746 }
747
748 if (!dtp->u.p.no_leading_blank)
749 {
746e6327 750 memset4 (p4, ' ', nblank);
c7421e06 751 q += nblank;
746e6327 752 memset4 (p4, '0', nzero);
c7421e06 753 q += nzero;
746e6327 754 memcpy4 (p4, q, digits);
c7421e06
JD
755 }
756 else
757 {
746e6327 758 memset4 (p4, '0', nzero);
c7421e06 759 q += nzero;
746e6327 760 memcpy4 (p4, q, digits);
c7421e06 761 q += digits;
746e6327 762 memset4 (p4, ' ', nblank);
c7421e06
JD
763 dtp->u.p.no_leading_blank = 0;
764 }
765 return;
766 }
767
6de9cd9a
DN
768 if (nblank < 0)
769 {
770 star_fill (p, w);
771 goto done;
772 }
773
5e805e44 774 if (!dtp->u.p.no_leading_blank)
29dc5138 775 {
5e805e44
JJ
776 memset (p, ' ', nblank);
777 p += nblank;
778 memset (p, '0', nzero);
779 p += nzero;
780 memcpy (p, q, digits);
29dc5138
PT
781 }
782 else
783 {
784 memset (p, '0', nzero);
785 p += nzero;
786 memcpy (p, q, digits);
787 p += digits;
788 memset (p, ' ', nblank);
5e805e44 789 dtp->u.p.no_leading_blank = 0;
29dc5138 790 }
6de9cd9a 791
f21edfd6 792 done:
6de9cd9a
DN
793 return;
794}
795
796static void
5e805e44 797write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
4ae906e4 798 int len)
6de9cd9a 799{
32aa3bff 800 GFC_INTEGER_LARGEST n = 0;
4ae906e4 801 GFC_UINTEGER_LARGEST absn;
6de9cd9a 802 int w, m, digits, nsign, nzero, nblank;
1449b8cb
JJ
803 char *p;
804 const char *q;
6de9cd9a 805 sign_t sign;
1449b8cb 806 char itoa_buf[GFC_BTOA_BUF_SIZE];
6de9cd9a
DN
807
808 w = f->u.integer.w;
9355110f 809 m = f->format == FMT_G ? -1 : f->u.integer.m;
6de9cd9a
DN
810
811 n = extract_int (source, len);
812
7fcb1804 813 /* Special case: */
6de9cd9a
DN
814 if (m == 0 && n == 0)
815 {
816 if (w == 0)
817 w = 1;
818
5e805e44 819 p = write_block (dtp, w);
6de9cd9a
DN
820 if (p == NULL)
821 return;
c7421e06 822 if (unlikely (is_char4_unit (dtp)))
746e6327
JD
823 {
824 gfc_char4_t *p4 = (gfc_char4_t *) p;
825 memset4 (p4, ' ', w);
826 }
c7421e06
JD
827 else
828 memset (p, ' ', w);
6de9cd9a
DN
829 goto done;
830 }
831
5e805e44 832 sign = calculate_sign (dtp, n < 0);
6de9cd9a 833 if (n < 0)
4ae906e4
FXC
834 /* Use unsigned to protect from overflow. */
835 absn = -(GFC_UINTEGER_LARGEST) n;
836 else
837 absn = n;
10256cbe 838 nsign = sign == S_NONE ? 0 : 1;
e73d3ca6 839
4ae906e4
FXC
840 /* gfc_itoa() converts the nonnegative value to decimal representation. */
841 q = gfc_itoa (absn, itoa_buf, sizeof (itoa_buf));
6de9cd9a
DN
842 digits = strlen (q);
843
844 /* Select a width if none was specified. The idea here is to always
7fcb1804 845 print something. */
88a8126a
JB
846 if (w == DEFAULT_WIDTH)
847 w = default_width_for_integer (len);
6de9cd9a
DN
848
849 if (w == 0)
850 w = ((digits < m) ? m : digits) + nsign;
851
5e805e44 852 p = write_block (dtp, w);
6de9cd9a
DN
853 if (p == NULL)
854 return;
855
856 nzero = 0;
857 if (digits < m)
858 nzero = m - digits;
859
7fcb1804 860 /* See if things will work. */
6de9cd9a
DN
861
862 nblank = w - (nsign + nzero + digits);
863
c7421e06
JD
864 if (unlikely (is_char4_unit (dtp)))
865 {
f29876bb 866 gfc_char4_t *p4 = (gfc_char4_t *)p;
c7421e06
JD
867 if (nblank < 0)
868 {
746e6327 869 memset4 (p4, '*', w);
c7421e06
JD
870 goto done;
871 }
872
a97de3cc
JD
873 if (!dtp->u.p.namelist_mode)
874 {
875 memset4 (p4, ' ', nblank);
876 p4 += nblank;
877 }
c7421e06
JD
878
879 switch (sign)
880 {
881 case S_PLUS:
882 *p4++ = '+';
883 break;
884 case S_MINUS:
885 *p4++ = '-';
886 break;
887 case S_NONE:
888 break;
889 }
890
746e6327 891 memset4 (p4, '0', nzero);
c7421e06
JD
892 p4 += nzero;
893
746e6327 894 memcpy4 (p4, q, digits);
c7421e06 895 return;
a97de3cc
JD
896
897 if (dtp->u.p.namelist_mode)
898 {
899 p4 += digits;
900 memset4 (p4, ' ', nblank);
901 }
c7421e06
JD
902 }
903
6de9cd9a
DN
904 if (nblank < 0)
905 {
906 star_fill (p, w);
907 goto done;
908 }
909
a97de3cc
JD
910 if (!dtp->u.p.namelist_mode)
911 {
912 memset (p, ' ', nblank);
913 p += nblank;
914 }
6de9cd9a
DN
915
916 switch (sign)
917 {
10256cbe 918 case S_PLUS:
6de9cd9a
DN
919 *p++ = '+';
920 break;
10256cbe 921 case S_MINUS:
6de9cd9a
DN
922 *p++ = '-';
923 break;
10256cbe 924 case S_NONE:
6de9cd9a
DN
925 break;
926 }
927
928 memset (p, '0', nzero);
929 p += nzero;
930
931 memcpy (p, q, digits);
932
a97de3cc
JD
933 if (dtp->u.p.namelist_mode)
934 {
935 p += digits;
936 memset (p, ' ', nblank);
937 }
938
f21edfd6 939 done:
6de9cd9a
DN
940 return;
941}
942
943
4ae906e4
FXC
944/* Convert hexadecimal to ASCII. */
945
946static const char *
947xtoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
948{
949 int digit;
950 char *p;
951
952 assert (len >= GFC_XTOA_BUF_SIZE);
953
954 if (n == 0)
955 return "0";
956
957 p = buffer + GFC_XTOA_BUF_SIZE - 1;
958 *p = '\0';
959
960 while (n != 0)
961 {
962 digit = n & 0xF;
963 if (digit > 9)
964 digit += 'A' - '0' - 10;
965
966 *--p = '0' + digit;
967 n >>= 4;
968 }
969
970 return p;
971}
972
973
974/* Convert unsigned octal to ASCII. */
6de9cd9a 975
1449b8cb
JJ
976static const char *
977otoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
6de9cd9a
DN
978{
979 char *p;
980
1449b8cb
JJ
981 assert (len >= GFC_OTOA_BUF_SIZE);
982
6de9cd9a 983 if (n == 0)
1449b8cb 984 return "0";
6de9cd9a 985
1449b8cb
JJ
986 p = buffer + GFC_OTOA_BUF_SIZE - 1;
987 *p = '\0';
6de9cd9a
DN
988
989 while (n != 0)
990 {
1449b8cb 991 *--p = '0' + (n & 7);
6de9cd9a
DN
992 n >>= 3;
993 }
994
1449b8cb 995 return p;
6de9cd9a
DN
996}
997
998
4ae906e4 999/* Convert unsigned binary to ASCII. */
6de9cd9a 1000
1449b8cb
JJ
1001static const char *
1002btoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
6de9cd9a
DN
1003{
1004 char *p;
1005
1449b8cb
JJ
1006 assert (len >= GFC_BTOA_BUF_SIZE);
1007
6de9cd9a 1008 if (n == 0)
1449b8cb 1009 return "0";
6de9cd9a 1010
1449b8cb
JJ
1011 p = buffer + GFC_BTOA_BUF_SIZE - 1;
1012 *p = '\0';
6de9cd9a
DN
1013
1014 while (n != 0)
1015 {
1449b8cb 1016 *--p = '0' + (n & 1);
6de9cd9a
DN
1017 n >>= 1;
1018 }
1019
1449b8cb 1020 return p;
6de9cd9a
DN
1021}
1022
4ae906e4 1023/* The following three functions, btoa_big, otoa_big, and xtoa_big, are needed
486024b1
JD
1024 to convert large reals with kind sizes that exceed the largest integer type
1025 available on certain platforms. In these cases, byte by byte conversion is
1026 performed. Endianess is taken into account. */
1027
1028/* Conversion to binary. */
1029
1030static const char *
1031btoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
1032{
1033 char *q;
1034 int i, j;
e73d3ca6 1035
486024b1 1036 q = buffer;
5675291d 1037 if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
486024b1
JD
1038 {
1039 const char *p = s;
1040 for (i = 0; i < len; i++)
1041 {
1042 char c = *p;
1043
1044 /* Test for zero. Needed by write_boz later. */
1045 if (*p != 0)
1046 *n = 1;
1047
1048 for (j = 0; j < 8; j++)
1049 {
1050 *q++ = (c & 128) ? '1' : '0';
1051 c <<= 1;
1052 }
1053 p++;
1054 }
1055 }
1056 else
1057 {
1058 const char *p = s + len - 1;
1059 for (i = 0; i < len; i++)
1060 {
1061 char c = *p;
1062
1063 /* Test for zero. Needed by write_boz later. */
1064 if (*p != 0)
1065 *n = 1;
1066
1067 for (j = 0; j < 8; j++)
1068 {
1069 *q++ = (c & 128) ? '1' : '0';
1070 c <<= 1;
1071 }
1072 p--;
1073 }
1074 }
1075
486024b1
JD
1076 if (*n == 0)
1077 return "0";
1078
e73d3ca6 1079 /* Move past any leading zeros. */
486024b1
JD
1080 while (*buffer == '0')
1081 buffer++;
1082
1083 return buffer;
1084
1085}
1086
1087/* Conversion to octal. */
1088
1089static const char *
1090otoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
1091{
1092 char *q;
1093 int i, j, k;
1094 uint8_t octet;
1095
1096 q = buffer + GFC_OTOA_BUF_SIZE - 1;
1097 *q = '\0';
1098 i = k = octet = 0;
1099
5675291d 1100 if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
486024b1
JD
1101 {
1102 const char *p = s + len - 1;
1103 char c = *p;
1104 while (i < len)
1105 {
1106 /* Test for zero. Needed by write_boz later. */
1107 if (*p != 0)
1108 *n = 1;
1109
1110 for (j = 0; j < 3 && i < len; j++)
1111 {
1112 octet |= (c & 1) << j;
1113 c >>= 1;
1114 if (++k > 7)
1115 {
1116 i++;
1117 k = 0;
1118 c = *--p;
1119 }
1120 }
1121 *--q = '0' + octet;
1122 octet = 0;
1123 }
1124 }
1125 else
1126 {
1127 const char *p = s;
1128 char c = *p;
1129 while (i < len)
1130 {
1131 /* Test for zero. Needed by write_boz later. */
1132 if (*p != 0)
1133 *n = 1;
1134
1135 for (j = 0; j < 3 && i < len; j++)
1136 {
1137 octet |= (c & 1) << j;
1138 c >>= 1;
1139 if (++k > 7)
1140 {
1141 i++;
1142 k = 0;
1143 c = *++p;
1144 }
1145 }
1146 *--q = '0' + octet;
1147 octet = 0;
1148 }
1149 }
1150
1151 if (*n == 0)
1152 return "0";
1153
e73d3ca6 1154 /* Move past any leading zeros. */
486024b1
JD
1155 while (*q == '0')
1156 q++;
1157
1158 return q;
1159}
1160
4ae906e4 1161/* Conversion to hexadecimal. */
486024b1
JD
1162
1163static const char *
4ae906e4 1164xtoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
486024b1
JD
1165{
1166 static char a[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
1167 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
1168
1169 char *q;
1170 uint8_t h, l;
1171 int i;
e73d3ca6 1172
486024b1 1173 q = buffer;
e73d3ca6 1174
5675291d 1175 if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
486024b1
JD
1176 {
1177 const char *p = s;
1178 for (i = 0; i < len; i++)
1179 {
1180 /* Test for zero. Needed by write_boz later. */
1181 if (*p != 0)
1182 *n = 1;
1183
1184 h = (*p >> 4) & 0x0F;
1185 l = *p++ & 0x0F;
1186 *q++ = a[h];
1187 *q++ = a[l];
1188 }
1189 }
1190 else
1191 {
1192 const char *p = s + len - 1;
1193 for (i = 0; i < len; i++)
1194 {
1195 /* Test for zero. Needed by write_boz later. */
1196 if (*p != 0)
1197 *n = 1;
1198
1199 h = (*p >> 4) & 0x0F;
1200 l = *p-- & 0x0F;
1201 *q++ = a[h];
1202 *q++ = a[l];
1203 }
1204 }
1205
4ae906e4 1206 /* write_z, which calls xtoa_big, is called from transfer.c,
0cfc34ad
TK
1207 formatted_transfer_scalar_write. There it is passed the kind as
1208 argument, which means a maximum of 16. The buffer is large
1209 enough, but the compiler does not know that, so shut up the
1210 warning here. */
1211#pragma GCC diagnostic push
1212#pragma GCC diagnostic ignored "-Wstringop-overflow"
486024b1 1213 *q = '\0';
0cfc34ad 1214#pragma GCC diagnostic pop
e73d3ca6 1215
486024b1
JD
1216 if (*n == 0)
1217 return "0";
e73d3ca6
PT
1218
1219 /* Move past any leading zeros. */
486024b1
JD
1220 while (*buffer == '0')
1221 buffer++;
1222
1223 return buffer;
1224}
6de9cd9a 1225
f9bfed22 1226
6de9cd9a 1227void
5e805e44 1228write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
6de9cd9a 1229{
4ae906e4 1230 write_decimal (dtp, f, p, len);
6de9cd9a
DN
1231}
1232
1233
1234void
486024b1 1235write_b (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
6de9cd9a 1236{
486024b1
JD
1237 const char *p;
1238 char itoa_buf[GFC_BTOA_BUF_SIZE];
1239 GFC_UINTEGER_LARGEST n = 0;
1240
a4626a7b
JD
1241 /* Ensure we end up with a null terminated string. */
1242 memset(itoa_buf, '\0', GFC_BTOA_BUF_SIZE);
1243
486024b1
JD
1244 if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
1245 {
1246 p = btoa_big (source, itoa_buf, len, &n);
88a8126a 1247 write_boz (dtp, f, p, n, len);
486024b1
JD
1248 }
1249 else
1250 {
1251 n = extract_uint (source, len);
1252 p = btoa (n, itoa_buf, sizeof (itoa_buf));
88a8126a 1253 write_boz (dtp, f, p, n, len);
486024b1 1254 }
6de9cd9a
DN
1255}
1256
1257
1258void
486024b1 1259write_o (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
6de9cd9a 1260{
486024b1
JD
1261 const char *p;
1262 char itoa_buf[GFC_OTOA_BUF_SIZE];
1263 GFC_UINTEGER_LARGEST n = 0;
e73d3ca6 1264
486024b1
JD
1265 if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
1266 {
1267 p = otoa_big (source, itoa_buf, len, &n);
88a8126a 1268 write_boz (dtp, f, p, n, len);
486024b1
JD
1269 }
1270 else
1271 {
1272 n = extract_uint (source, len);
1273 p = otoa (n, itoa_buf, sizeof (itoa_buf));
88a8126a 1274 write_boz (dtp, f, p, n, len);
486024b1 1275 }
6de9cd9a
DN
1276}
1277
1278void
486024b1 1279write_z (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
6de9cd9a 1280{
486024b1
JD
1281 const char *p;
1282 char itoa_buf[GFC_XTOA_BUF_SIZE];
1283 GFC_UINTEGER_LARGEST n = 0;
1284
1285 if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
1286 {
4ae906e4 1287 p = xtoa_big (source, itoa_buf, len, &n);
88a8126a 1288 write_boz (dtp, f, p, n, len);
486024b1
JD
1289 }
1290 else
1291 {
1292 n = extract_uint (source, len);
4ae906e4 1293 p = xtoa (n, itoa_buf, sizeof (itoa_buf));
88a8126a 1294 write_boz (dtp, f, p, n, len);
486024b1 1295 }
6de9cd9a
DN
1296}
1297
7fcb1804 1298/* Take care of the X/TR descriptor. */
6de9cd9a
DN
1299
1300void
5e805e44 1301write_x (st_parameter_dt *dtp, int len, int nspaces)
6de9cd9a
DN
1302{
1303 char *p;
1304
5e805e44 1305 p = write_block (dtp, len);
6de9cd9a
DN
1306 if (p == NULL)
1307 return;
7812c78c 1308 if (nspaces > 0 && len - nspaces >= 0)
c7421e06
JD
1309 {
1310 if (unlikely (is_char4_unit (dtp)))
746e6327
JD
1311 {
1312 gfc_char4_t *p4 = (gfc_char4_t *) p;
1313 memset4 (&p4[len - nspaces], ' ', nspaces);
1314 }
c7421e06
JD
1315 else
1316 memset (&p[len - nspaces], ' ', nspaces);
1317 }
6de9cd9a
DN
1318}
1319
1320
7fcb1804 1321/* List-directed writing. */
6de9cd9a
DN
1322
1323
7fcb1804
TS
1324/* Write a single character to the output. Returns nonzero if
1325 something goes wrong. */
6de9cd9a
DN
1326
1327static int
746e6327 1328write_char (st_parameter_dt *dtp, int c)
6de9cd9a
DN
1329{
1330 char *p;
1331
5e805e44 1332 p = write_block (dtp, 1);
6de9cd9a
DN
1333 if (p == NULL)
1334 return 1;
746e6327
JD
1335 if (unlikely (is_char4_unit (dtp)))
1336 {
1337 gfc_char4_t *p4 = (gfc_char4_t *) p;
1338 *p4 = c;
1339 return 0;
1340 }
6de9cd9a 1341
746e6327 1342 *p = (uchar) c;
6de9cd9a
DN
1343
1344 return 0;
1345}
1346
1347
7fcb1804 1348/* Write a list-directed logical value. */
d464f8e9 1349
6de9cd9a 1350static void
5e805e44 1351write_logical (st_parameter_dt *dtp, const char *source, int length)
6de9cd9a 1352{
5e805e44 1353 write_char (dtp, extract_int (source, length) ? 'T' : 'F');
6de9cd9a
DN
1354}
1355
1356
7fcb1804 1357/* Write a list-directed integer value. */
6de9cd9a
DN
1358
1359static void
a97de3cc 1360write_integer (st_parameter_dt *dtp, const char *source, int kind)
6de9cd9a 1361{
d464f8e9 1362 int width;
a97de3cc 1363 fnode f;
6de9cd9a 1364
a97de3cc 1365 switch (kind)
d464f8e9
JB
1366 {
1367 case 1:
1368 width = 4;
1369 break;
1370
1371 case 2:
1372 width = 6;
1373 break;
1374
1375 case 4:
1376 width = 11;
1377 break;
1378
1379 case 8:
1380 width = 20;
1381 break;
1382
b8f41284
DH
1383 case 16:
1384 width = 40;
1385 break;
1386
d464f8e9
JB
1387 default:
1388 width = 0;
1389 break;
1390 }
a97de3cc
JD
1391 f.u.integer.w = width;
1392 f.u.integer.m = -1;
8cb19ee3 1393 f.format = FMT_NONE;
4ae906e4 1394 write_decimal (dtp, &f, source, kind);
6de9cd9a
DN
1395}
1396
1397
7fcb1804
TS
1398/* Write a list-directed string. We have to worry about delimiting
1399 the strings if the file has been opened in that mode. */
6de9cd9a 1400
75b2dba9
JD
1401#define DELIM 1
1402#define NODELIM 0
1403
6de9cd9a 1404static void
d9bb51cd 1405write_character (st_parameter_dt *dtp, const char *source, int kind, size_t length, int mode)
6de9cd9a 1406{
d9bb51cd 1407 size_t extra;
6de9cd9a
DN
1408 char *p, d;
1409
75b2dba9 1410 if (mode == DELIM)
6de9cd9a 1411 {
75b2dba9
JD
1412 switch (dtp->u.p.current_unit->delim_status)
1413 {
1414 case DELIM_APOSTROPHE:
1415 d = '\'';
1416 break;
1417 case DELIM_QUOTE:
1418 d = '"';
1419 break;
1420 default:
1421 d = ' ';
1422 break;
1423 }
6de9cd9a 1424 }
75b2dba9
JD
1425 else
1426 d = ' ';
6de9cd9a 1427
cea93abb 1428 if (kind == 1)
6de9cd9a 1429 {
cea93abb
JD
1430 if (d == ' ')
1431 extra = 0;
1432 else
1433 {
1434 extra = 2;
6de9cd9a 1435
d9bb51cd 1436 for (size_t i = 0; i < length; i++)
3ae86bf4
JD
1437 if (source[i] == d)
1438 extra++;
cea93abb 1439 }
6de9cd9a 1440
cea93abb
JD
1441 p = write_block (dtp, length + extra);
1442 if (p == NULL)
1443 return;
1444
74db2a47
JD
1445 if (unlikely (is_char4_unit (dtp)))
1446 {
1447 gfc_char4_t d4 = (gfc_char4_t) d;
1448 gfc_char4_t *p4 = (gfc_char4_t *) p;
1449
1450 if (d4 == ' ')
746e6327 1451 memcpy4 (p4, source, length);
74db2a47
JD
1452 else
1453 {
1454 *p4++ = d4;
1455
d9bb51cd 1456 for (size_t i = 0; i < length; i++)
74db2a47
JD
1457 {
1458 *p4++ = (gfc_char4_t) source[i];
1459 if (source[i] == d)
1460 *p4++ = d4;
1461 }
1462
1463 *p4 = d4;
1464 }
1465 return;
1466 }
1467
cea93abb
JD
1468 if (d == ' ')
1469 memcpy (p, source, length);
1470 else
1471 {
1472 *p++ = d;
6de9cd9a 1473
d9bb51cd 1474 for (size_t i = 0; i < length; i++)
cea93abb
JD
1475 {
1476 *p++ = source[i];
1477 if (source[i] == d)
1478 *p++ = d;
1479 }
1480
1481 *p = d;
1482 }
1483 }
6de9cd9a
DN
1484 else
1485 {
cea93abb 1486 if (d == ' ')
6de9cd9a 1487 {
3ae86bf4
JD
1488 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
1489 write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
1490 else
1491 write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
cea93abb
JD
1492 }
1493 else
1494 {
3ae86bf4
JD
1495 p = write_block (dtp, 1);
1496 *p = d;
1497
1498 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
1499 write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
1500 else
1501 write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
1502
1503 p = write_block (dtp, 1);
cea93abb
JD
1504 *p = d;
1505 }
6de9cd9a
DN
1506 }
1507}
1508
5b0e27a7
JD
1509/* Floating point helper functions. */
1510
8cb19ee3 1511#define BUF_STACK_SZ 384
5b0e27a7
JD
1512
1513static int
1514get_precision (st_parameter_dt *dtp, const fnode *f, const char *source, int kind)
1515{
1516 if (f->format != FMT_EN)
1517 return determine_precision (dtp, f, kind);
1518 else
1519 return determine_en_precision (dtp, f, source, kind);
1520}
1521
d7756960
JD
1522/* 4932 is the maximum exponent of long double and quad precision, 3
1523 extra characters for the sign, the decimal point, and the
1524 trailing null. Extra digits are added by the calling functions for
1525 requested precision. Likewise for float and double. F0 editing produces
1526 full precision output. */
1527static int
1528size_from_kind (st_parameter_dt *dtp, const fnode *f, int kind)
1529{
1530 int size;
1531
88a8126a 1532 if ((f->format == FMT_F && f->u.real.w == 0) || f->u.real.w == DEFAULT_WIDTH)
d7756960
JD
1533 {
1534 switch (kind)
1535 {
1536 case 4:
1537 size = 38 + 3; /* These constants shown for clarity. */
1538 break;
1539 case 8:
1540 size = 308 + 3;
1541 break;
1542 case 10:
1543 size = 4932 + 3;
1544 break;
1545 case 16:
1546 size = 4932 + 3;
1547 break;
1548 default:
1549 internal_error (&dtp->common, "bad real kind");
1550 break;
1551 }
1552 }
1553 else
1554 size = f->u.real.w + 1; /* One byte for a NULL character. */
1555
1556 return size;
1557}
1558
5b0e27a7 1559static char *
d7756960
JD
1560select_buffer (st_parameter_dt *dtp, const fnode *f, int precision,
1561 char *buf, size_t *size, int kind)
5b0e27a7
JD
1562{
1563 char *result;
d7756960 1564
33b2b069
JD
1565 /* The buffer needs at least one more byte to allow room for
1566 normalizing and 1 to hold null terminator. */
1567 *size = size_from_kind (dtp, f, kind) + precision + 1 + 1;
d7756960 1568
5b0e27a7
JD
1569 if (*size > BUF_STACK_SZ)
1570 result = xmalloc (*size);
1571 else
1572 result = buf;
1573 return result;
1574}
1575
1576static char *
d7756960
JD
1577select_string (st_parameter_dt *dtp, const fnode *f, char *buf, size_t *size,
1578 int kind)
5b0e27a7
JD
1579{
1580 char *result;
b7c44c8f 1581 *size = size_from_kind (dtp, f, kind) + f->u.real.d + 1;
5b0e27a7
JD
1582 if (*size > BUF_STACK_SZ)
1583 result = xmalloc (*size);
1584 else
1585 result = buf;
1586 return result;
1587}
1588
1589static void
1590write_float_string (st_parameter_dt *dtp, char *fstr, size_t len)
1591{
1592 char *p = write_block (dtp, len);
1593 if (p == NULL)
1594 return;
1595
1596 if (unlikely (is_char4_unit (dtp)))
1597 {
1598 gfc_char4_t *p4 = (gfc_char4_t *) p;
1599 memcpy4 (p4, fstr, len);
1600 return;
1601 }
1602 memcpy (p, fstr, len);
1603}
1604
d7756960 1605
5b0e27a7
JD
1606static void
1607write_float_0 (st_parameter_dt *dtp, const fnode *f, const char *source, int kind)
1608{
1609 char buf_stack[BUF_STACK_SZ];
1610 char str_buf[BUF_STACK_SZ];
1611 char *buffer, *result;
3c2ce893 1612 size_t buf_size, res_len, flt_str_len;
5b0e27a7
JD
1613
1614 /* Precision for snprintf call. */
1615 int precision = get_precision (dtp, f, source, kind);
e73d3ca6 1616
5b0e27a7 1617 /* String buffer to hold final result. */
d7756960 1618 result = select_string (dtp, f, str_buf, &res_len, kind);
3c2ce893 1619
d7756960 1620 buffer = select_buffer (dtp, f, precision, buf_stack, &buf_size, kind);
3c2ce893 1621
5b0e27a7 1622 get_float_string (dtp, f, source , kind, 0, buffer,
3c2ce893
JD
1623 precision, buf_size, result, &flt_str_len);
1624 write_float_string (dtp, result, flt_str_len);
5b0e27a7
JD
1625
1626 if (buf_size > BUF_STACK_SZ)
1627 free (buffer);
1628 if (res_len > BUF_STACK_SZ)
1629 free (result);
1630}
1631
1632void
1633write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1634{
1635 write_float_0 (dtp, f, p, len);
1636}
1637
1638
1639void
1640write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1641{
1642 write_float_0 (dtp, f, p, len);
1643}
1644
1645
1646void
1647write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1648{
1649 write_float_0 (dtp, f, p, len);
1650}
1651
1652
1653void
1654write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1655{
1656 write_float_0 (dtp, f, p, len);
1657}
1658
1659
1660void
1661write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1662{
1663 write_float_0 (dtp, f, p, len);
1664}
1665
6de9cd9a 1666
900e887f 1667/* Set an fnode to default format. */
6de9cd9a 1668
900e887f
JD
1669static void
1670set_fnode_default (st_parameter_dt *dtp, fnode *f, int length)
6de9cd9a 1671{
900e887f 1672 f->format = FMT_G;
6d56728a 1673 switch (length)
6de9cd9a 1674 {
6d56728a 1675 case 4:
a3f02fe4
JD
1676 f->u.real.w = 16;
1677 f->u.real.d = 9;
900e887f 1678 f->u.real.e = 2;
6d56728a
FXC
1679 break;
1680 case 8:
900e887f
JD
1681 f->u.real.w = 25;
1682 f->u.real.d = 17;
1683 f->u.real.e = 3;
6d56728a
FXC
1684 break;
1685 case 10:
a3f02fe4
JD
1686 f->u.real.w = 30;
1687 f->u.real.d = 21;
900e887f 1688 f->u.real.e = 4;
6d56728a
FXC
1689 break;
1690 case 16:
8d3586e4
JD
1691 /* Adjust decimal precision depending on binary precision, 106 or 113. */
1692#if GFC_REAL_16_DIGITS == 113
a3f02fe4
JD
1693 f->u.real.w = 45;
1694 f->u.real.d = 36;
900e887f 1695 f->u.real.e = 4;
8d3586e4
JD
1696#else
1697 f->u.real.w = 41;
1698 f->u.real.d = 32;
1699 f->u.real.e = 4;
1700#endif
6d56728a
FXC
1701 break;
1702 default:
5e805e44 1703 internal_error (&dtp->common, "bad real kind");
6d56728a 1704 break;
6de9cd9a 1705 }
900e887f 1706}
d785f6a3 1707
5b0e27a7
JD
1708/* Output a real number with default format.
1709 To guarantee that a binary -> decimal -> binary roundtrip conversion
1710 recovers the original value, IEEE 754-2008 requires 9, 17, 21 and 36
1711 significant digits for REAL kinds 4, 8, 10, and 16, respectively.
1712 Thus, we use 1PG16.9E2 for REAL(4), 1PG25.17E3 for REAL(8), 1PG30.21E4
1713 for REAL(10) and 1PG45.36E4 for REAL(16). The exception is that the
ef6d0b67
JB
1714 Fortran standard requires outputting an extra digit when the scale
1715 factor is 1 and when the magnitude of the value is such that E
1716 editing is used. However, gfortran compensates for this, and thus
1717 for list formatted the same number of significant digits is
1718 generated both when using F and E editing. */
900e887f
JD
1719
1720void
5b0e27a7 1721write_real (st_parameter_dt *dtp, const char *source, int kind)
900e887f
JD
1722{
1723 fnode f ;
5b0e27a7
JD
1724 char buf_stack[BUF_STACK_SZ];
1725 char str_buf[BUF_STACK_SZ];
1726 char *buffer, *result;
1f161c48 1727 size_t buf_size, res_len, flt_str_len;
5b0e27a7 1728 int orig_scale = dtp->u.p.scale_factor;
900e887f 1729 dtp->u.p.scale_factor = 1;
5b0e27a7
JD
1730 set_fnode_default (dtp, &f, kind);
1731
1732 /* Precision for snprintf call. */
1733 int precision = get_precision (dtp, &f, source, kind);
e73d3ca6 1734
5b0e27a7 1735 /* String buffer to hold final result. */
d7756960 1736 result = select_string (dtp, &f, str_buf, &res_len, kind);
e73d3ca6 1737
d7756960
JD
1738 /* Scratch buffer to hold final result. */
1739 buffer = select_buffer (dtp, &f, precision, buf_stack, &buf_size, kind);
1740
5b0e27a7 1741 get_float_string (dtp, &f, source , kind, 1, buffer,
1f161c48
JD
1742 precision, buf_size, result, &flt_str_len);
1743 write_float_string (dtp, result, flt_str_len);
5b0e27a7
JD
1744
1745 dtp->u.p.scale_factor = orig_scale;
1746 if (buf_size > BUF_STACK_SZ)
1747 free (buffer);
1748 if (res_len > BUF_STACK_SZ)
1749 free (result);
900e887f
JD
1750}
1751
d785f6a3
JB
1752/* Similar to list formatted REAL output, for kPG0 where k > 0 we
1753 compensate for the extra digit. */
900e887f
JD
1754
1755void
67732fbc 1756write_real_w0 (st_parameter_dt *dtp, const char *source, int kind,
2b70275e 1757 const fnode* f)
900e887f 1758{
2b70275e 1759 fnode ff;
5b0e27a7
JD
1760 char buf_stack[BUF_STACK_SZ];
1761 char str_buf[BUF_STACK_SZ];
1762 char *buffer, *result;
1f161c48 1763 size_t buf_size, res_len, flt_str_len;
67732fbc 1764 int comp_d = 0;
5b0e27a7 1765
2b70275e
JD
1766 set_fnode_default (dtp, &ff, kind);
1767
1768 if (f->u.real.d > 0)
1769 ff.u.real.d = f->u.real.d;
1770 ff.format = f->format;
67732fbc
JD
1771
1772 /* For FMT_G, Compensate for extra digits when using scale factor, d
1773 is not specified, and the magnitude is such that E editing
1774 is used. */
2b70275e 1775 if (f->format == FMT_G)
67732fbc 1776 {
2b70275e 1777 if (dtp->u.p.scale_factor > 0 && f->u.real.d == 0)
67732fbc
JD
1778 comp_d = 1;
1779 else
1780 comp_d = 0;
1781 }
a3f02fe4 1782
2b70275e
JD
1783 if (f->u.real.e >= 0)
1784 ff.u.real.e = f->u.real.e;
1785
50220190 1786 dtp->u.p.g0_no_blanks = 1;
5b0e27a7
JD
1787
1788 /* Precision for snprintf call. */
2b70275e 1789 int precision = get_precision (dtp, &ff, source, kind);
e73d3ca6 1790
5b0e27a7 1791 /* String buffer to hold final result. */
2b70275e 1792 result = select_string (dtp, &ff, str_buf, &res_len, kind);
5b0e27a7 1793
2b70275e 1794 buffer = select_buffer (dtp, &ff, precision, buf_stack, &buf_size, kind);
5b0e27a7 1795
2b70275e 1796 get_float_string (dtp, &ff, source , kind, comp_d, buffer,
67732fbc 1797 precision, buf_size, result, &flt_str_len);
1f161c48 1798 write_float_string (dtp, result, flt_str_len);
5b0e27a7 1799
50220190 1800 dtp->u.p.g0_no_blanks = 0;
5b0e27a7
JD
1801 if (buf_size > BUF_STACK_SZ)
1802 free (buffer);
1803 if (res_len > BUF_STACK_SZ)
1804 free (result);
6de9cd9a
DN
1805}
1806
1807
1808static void
5e805e44 1809write_complex (st_parameter_dt *dtp, const char *source, int kind, size_t size)
6de9cd9a 1810{
105b7136
JD
1811 char semi_comma =
1812 dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';';
10256cbe 1813
5b0e27a7
JD
1814 /* Set for no blanks so we get a string result with no leading
1815 blanks. We will pad left later. */
1816 dtp->u.p.g0_no_blanks = 1;
6de9cd9a 1817
5b0e27a7
JD
1818 fnode f ;
1819 char buf_stack[BUF_STACK_SZ];
1820 char str1_buf[BUF_STACK_SZ];
1821 char str2_buf[BUF_STACK_SZ];
1822 char *buffer, *result1, *result2;
1f161c48 1823 size_t buf_size, res_len1, res_len2, flt_str_len1, flt_str_len2;
5b0e27a7 1824 int width, lblanks, orig_scale = dtp->u.p.scale_factor;
6de9cd9a 1825
5b0e27a7
JD
1826 dtp->u.p.scale_factor = 1;
1827 set_fnode_default (dtp, &f, kind);
e73d3ca6 1828
5b0e27a7
JD
1829 /* Set width for two values, parenthesis, and comma. */
1830 width = 2 * f.u.real.w + 3;
1831
1832 /* Set for no blanks so we get a string result with no leading
1833 blanks. We will pad left later. */
1834 dtp->u.p.g0_no_blanks = 1;
e73d3ca6 1835
5b0e27a7
JD
1836 /* Precision for snprintf call. */
1837 int precision = get_precision (dtp, &f, source, kind);
e73d3ca6 1838
5b0e27a7 1839 /* String buffers to hold final result. */
d7756960
JD
1840 result1 = select_string (dtp, &f, str1_buf, &res_len1, kind);
1841 result2 = select_string (dtp, &f, str2_buf, &res_len2, kind);
5b0e27a7 1842
d7756960 1843 buffer = select_buffer (dtp, &f, precision, buf_stack, &buf_size, kind);
e73d3ca6 1844
5b0e27a7 1845 get_float_string (dtp, &f, source , kind, 0, buffer,
1f161c48 1846 precision, buf_size, result1, &flt_str_len1);
5b0e27a7 1847 get_float_string (dtp, &f, source + size / 2 , kind, 0, buffer,
1f161c48 1848 precision, buf_size, result2, &flt_str_len2);
c4508d0a
JD
1849 if (!dtp->u.p.namelist_mode)
1850 {
1f161c48 1851 lblanks = width - flt_str_len1 - flt_str_len2 - 3;
c4508d0a
JD
1852 write_x (dtp, lblanks, lblanks);
1853 }
5b0e27a7 1854 write_char (dtp, '(');
1f161c48 1855 write_float_string (dtp, result1, flt_str_len1);
5b0e27a7 1856 write_char (dtp, semi_comma);
1f161c48 1857 write_float_string (dtp, result2, flt_str_len2);
5e805e44 1858 write_char (dtp, ')');
e73d3ca6 1859
5b0e27a7
JD
1860 dtp->u.p.scale_factor = orig_scale;
1861 dtp->u.p.g0_no_blanks = 0;
1862 if (buf_size > BUF_STACK_SZ)
1863 free (buffer);
1864 if (res_len1 > BUF_STACK_SZ)
1865 free (result1);
1866 if (res_len2 > BUF_STACK_SZ)
1867 free (result2);
6de9cd9a
DN
1868}
1869
1870
7fcb1804 1871/* Write the separator between items. */
6de9cd9a
DN
1872
1873static void
5e805e44 1874write_separator (st_parameter_dt *dtp)
6de9cd9a
DN
1875{
1876 char *p;
1877
5e805e44 1878 p = write_block (dtp, options.separator_len);
6de9cd9a
DN
1879 if (p == NULL)
1880 return;
746e6327
JD
1881 if (unlikely (is_char4_unit (dtp)))
1882 {
1883 gfc_char4_t *p4 = (gfc_char4_t *) p;
1884 memcpy4 (p4, options.separator, options.separator_len);
1885 }
1886 else
1887 memcpy (p, options.separator, options.separator_len);
6de9cd9a
DN
1888}
1889
1890
7fcb1804
TS
1891/* Write an item with list formatting.
1892 TODO: handle skipping to the next record correctly, particularly
1893 with strings. */
6de9cd9a 1894
18623fae 1895static void
5e805e44
JJ
1896list_formatted_write_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
1897 size_t size)
6de9cd9a 1898{
5e805e44 1899 if (dtp->u.p.current_unit == NULL)
6de9cd9a
DN
1900 return;
1901
5e805e44 1902 if (dtp->u.p.first_item)
6de9cd9a 1903 {
5e805e44 1904 dtp->u.p.first_item = 0;
0ef33d44
FR
1905 if (dtp->u.p.current_unit->flags.cc != CC_FORTRAN)
1906 write_char (dtp, ' ');
6de9cd9a
DN
1907 }
1908 else
1909 {
105b7136 1910 if (type != BT_CHARACTER || !dtp->u.p.char_flag ||
75b2dba9
JD
1911 (dtp->u.p.current_unit->delim_status != DELIM_NONE
1912 && dtp->u.p.current_unit->delim_status != DELIM_UNSPECIFIED))
105b7136 1913 write_separator (dtp);
6de9cd9a
DN
1914 }
1915
1916 switch (type)
1917 {
1918 case BT_INTEGER:
5e805e44 1919 write_integer (dtp, p, kind);
6de9cd9a
DN
1920 break;
1921 case BT_LOGICAL:
5e805e44 1922 write_logical (dtp, p, kind);
6de9cd9a
DN
1923 break;
1924 case BT_CHARACTER:
75b2dba9 1925 write_character (dtp, p, kind, size, DELIM);
6de9cd9a
DN
1926 break;
1927 case BT_REAL:
5e805e44 1928 write_real (dtp, p, kind);
6de9cd9a
DN
1929 break;
1930 case BT_COMPLEX:
5e805e44 1931 write_complex (dtp, p, kind, size);
6de9cd9a 1932 break;
e73d3ca6
PT
1933 case BT_CLASS:
1934 {
1935 int unit = dtp->u.p.current_unit->unit_number;
1936 char iotype[] = "LISTDIRECTED";
1937 gfc_charlen_type iotype_len = 12;
1938 char tmp_iomsg[IOMSG_LEN] = "";
1939 char *child_iomsg;
1940 gfc_charlen_type child_iomsg_len;
1941 int noiostat;
1942 int *child_iostat = NULL;
e9bfdf18 1943 gfc_full_array_i4 vlist;
e73d3ca6
PT
1944
1945 GFC_DESCRIPTOR_DATA(&vlist) = NULL;
1946 GFC_DIMENSION_SET(vlist.dim[0],1, 0, 0);
1947
1948 /* Set iostat, intent(out). */
1949 noiostat = 0;
1950 child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
1951 dtp->common.iostat : &noiostat;
1952
1953 /* Set iomsge, intent(inout). */
1954 if (dtp->common.flags & IOPARM_HAS_IOMSG)
1955 {
1956 child_iomsg = dtp->common.iomsg;
1957 child_iomsg_len = dtp->common.iomsg_len;
1958 }
1959 else
1960 {
1961 child_iomsg = tmp_iomsg;
1962 child_iomsg_len = IOMSG_LEN;
1963 }
1964
1965 /* Call the user defined formatted WRITE procedure. */
1966 dtp->u.p.current_unit->child_dtio++;
1967 dtp->u.p.fdtio_ptr (p, &unit, iotype, &vlist,
1968 child_iostat, child_iomsg,
1969 iotype_len, child_iomsg_len);
1970 dtp->u.p.current_unit->child_dtio--;
1971 }
1972 break;
6de9cd9a 1973 default:
5e805e44 1974 internal_error (&dtp->common, "list_formatted_write(): Bad type");
6de9cd9a
DN
1975 }
1976
1060d940 1977 fbuf_flush_list (dtp->u.p.current_unit, LIST_WRITING);
5e805e44 1978 dtp->u.p.char_flag = (type == BT_CHARACTER);
6de9cd9a
DN
1979}
1980
18623fae
JB
1981
1982void
5e805e44
JJ
1983list_formatted_write (st_parameter_dt *dtp, bt type, void *p, int kind,
1984 size_t size, size_t nelems)
18623fae
JB
1985{
1986 size_t elem;
18623fae 1987 char *tmp;
cea93abb
JD
1988 size_t stride = type == BT_CHARACTER ?
1989 size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
18623fae
JB
1990
1991 tmp = (char *) p;
1992
18623fae
JB
1993 /* Big loop over all the elements. */
1994 for (elem = 0; elem < nelems; elem++)
1995 {
5e805e44 1996 dtp->u.p.item_count++;
cea93abb 1997 list_formatted_write_scalar (dtp, type, tmp + elem * stride, kind, size);
18623fae
JB
1998 }
1999}
2000
29dc5138 2001/* NAMELIST OUTPUT
6de9cd9a 2002
29dc5138
PT
2003 nml_write_obj writes a namelist object to the output stream. It is called
2004 recursively for derived type components:
2005 obj = is the namelist_info for the current object.
2006 offset = the offset relative to the address held by the object for
2007 derived type arrays.
2008 base = is the namelist_info of the derived type, when obj is a
2009 component.
2010 base_name = the full name for a derived type, including qualifiers
2011 if any.
2012 The returned value is a pointer to the object beyond the last one
2013 accessed, including nested derived types. Notice that the namelist is
2014 a linear linked list of objects, including derived types and their
2015 components. A tree, of sorts, is implied by the compound names of
2016 the derived type components and this is how this function recurses through
2017 the list. */
6de9cd9a 2018
29dc5138
PT
2019/* A generous estimate of the number of characters needed to print
2020 repeat counts and indices, including commas, asterices and brackets. */
2021
2022#define NML_DIGITS 20
2023
8c8627c4
JD
2024static void
2025namelist_write_newline (st_parameter_dt *dtp)
2026{
2027 if (!is_internal_unit (dtp))
2028 {
2029#ifdef HAVE_CRLF
75b2dba9 2030 write_character (dtp, "\r\n", 1, 2, NODELIM);
8c8627c4 2031#else
75b2dba9 2032 write_character (dtp, "\n", 1, 1, NODELIM);
8c8627c4 2033#endif
94bc6c1e
JD
2034 return;
2035 }
2036
2037 if (is_array_io (dtp))
2038 {
2039 gfc_offset record;
14ca4cf8 2040 int finished;
4363c7a1
JD
2041 char *p;
2042 int length = dtp->u.p.current_unit->bytes_left;
2043
2044 p = write_block (dtp, length);
2045 if (p == NULL)
2046 return;
2047
2048 if (unlikely (is_char4_unit (dtp)))
2049 {
2050 gfc_char4_t *p4 = (gfc_char4_t *) p;
2051 memset4 (p4, ' ', length);
2052 }
2053 else
2054 memset (p, ' ', length);
94bc6c1e 2055
94bc6c1e
JD
2056 /* Now that the current record has been padded out,
2057 determine where the next record in the array is. */
2058 record = next_array_record (dtp, dtp->u.p.current_unit->ls,
2059 &finished);
2060 if (finished)
2061 dtp->u.p.current_unit->endfile = AT_ENDFILE;
2062 else
2063 {
2064 /* Now seek to this record */
2065 record = record * dtp->u.p.current_unit->recl;
2066
7812c78c 2067 if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
94bc6c1e
JD
2068 {
2069 generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
2070 return;
2071 }
2072
2073 dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
2074 }
8c8627c4
JD
2075 }
2076 else
75b2dba9 2077 write_character (dtp, " ", 1, 1, NODELIM);
8c8627c4
JD
2078}
2079
2080
29dc5138 2081static namelist_info *
f29876bb
JD
2082nml_write_obj (st_parameter_dt *dtp, namelist_info *obj, index_type offset,
2083 namelist_info *base, char *base_name)
29dc5138
PT
2084{
2085 int rep_ctr;
2086 int num;
2087 int nml_carry;
f9bfed22 2088 int len;
29dc5138
PT
2089 index_type obj_size;
2090 index_type nelem;
f9bfed22
JB
2091 size_t dim_i;
2092 size_t clen;
29dc5138 2093 index_type elem_ctr;
f9bfed22 2094 size_t obj_name_len;
f29876bb 2095 void *p;
29dc5138 2096 char cup;
f29876bb
JD
2097 char *obj_name;
2098 char *ext_name;
2099 char *q;
d30fe1c5 2100 size_t ext_name_len;
29dc5138 2101 char rep_buff[NML_DIGITS];
f29876bb
JD
2102 namelist_info *cmp;
2103 namelist_info *retval = obj->next;
88fdfd5a
JB
2104 size_t base_name_len;
2105 size_t base_var_name_len;
2106 size_t tot_len;
e73d3ca6 2107
10256cbe
JD
2108 /* Set the character to be used to separate values
2109 to a comma or semi-colon. */
2110
105b7136
JD
2111 char semi_comma =
2112 dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';';
29dc5138
PT
2113
2114 /* Write namelist variable names in upper case. If a derived type,
2115 nothing is output. If a component, base and base_name are set. */
2116
cf474530 2117 if (obj->type != BT_DERIVED || obj->dtio_sub != NULL)
b10cf173 2118 {
8c8627c4 2119 namelist_write_newline (dtp);
75b2dba9 2120 write_character (dtp, " ", 1, 1, NODELIM);
8c8627c4 2121
29dc5138
PT
2122 len = 0;
2123 if (base)
b10cf173 2124 {
f9bfed22
JB
2125 len = strlen (base->var_name);
2126 base_name_len = strlen (base_name);
2127 for (dim_i = 0; dim_i < base_name_len; dim_i++)
3bc268e6 2128 {
21423a1d 2129 cup = safe_toupper (base_name[dim_i]);
75b2dba9 2130 write_character (dtp, &cup, 1, 1, NODELIM);
3bc268e6 2131 }
29dc5138 2132 }
f9bfed22
JB
2133 clen = strlen (obj->var_name);
2134 for (dim_i = len; dim_i < clen; dim_i++)
29dc5138 2135 {
21423a1d 2136 cup = safe_toupper (obj->var_name[dim_i]);
9c5b1bf7
JD
2137 if (cup == '+')
2138 cup = '%';
75b2dba9 2139 write_character (dtp, &cup, 1, 1, NODELIM);
29dc5138 2140 }
75b2dba9 2141 write_character (dtp, "=", 1, 1, NODELIM);
29dc5138
PT
2142 }
2143
2144 /* Counts the number of data output on a line, including names. */
2145
2146 num = 1;
2147
2148 len = obj->len;
e5ef4b3b
JB
2149
2150 switch (obj->type)
2151 {
2152
a11930ba 2153 case BT_REAL:
e5ef4b3b
JB
2154 obj_size = size_from_real_kind (len);
2155 break;
2156
a11930ba 2157 case BT_COMPLEX:
e5ef4b3b
JB
2158 obj_size = size_from_complex_kind (len);
2159 break;
2160
a11930ba 2161 case BT_CHARACTER:
e5ef4b3b
JB
2162 obj_size = obj->string_length;
2163 break;
2164
2165 default:
e73d3ca6 2166 obj_size = len;
e5ef4b3b
JB
2167 }
2168
29dc5138
PT
2169 if (obj->var_rank)
2170 obj_size = obj->size;
2171
2172 /* Set the index vector and count the number of elements. */
2173
2174 nelem = 1;
f9bfed22 2175 for (dim_i = 0; dim_i < (size_t) obj->var_rank; dim_i++)
29dc5138 2176 {
dfb55fdc
TK
2177 obj->ls[dim_i].idx = GFC_DESCRIPTOR_LBOUND(obj, dim_i);
2178 nelem = nelem * GFC_DESCRIPTOR_EXTENT (obj, dim_i);
29dc5138
PT
2179 }
2180
2181 /* Main loop to output the data held in the object. */
2182
2183 rep_ctr = 1;
2184 for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
2185 {
2186
2187 /* Build the pointer to the data value. The offset is passed by
2188 recursive calls to this function for arrays of derived types.
2189 Is NULL otherwise. */
2190
2191 p = (void *)(obj->mem_pos + elem_ctr * obj_size);
2192 p += offset;
2193
2194 /* Check for repeat counts of intrinsic types. */
2195
2196 if ((elem_ctr < (nelem - 1)) &&
a11930ba 2197 (obj->type != BT_DERIVED) &&
f29876bb 2198 !memcmp (p, (void *)(p + obj_size ), obj_size ))
29dc5138
PT
2199 {
2200 rep_ctr++;
2201 }
2202
2203 /* Execute a repeated output. Note the flag no_leading_blank that
2204 is used in the functions used to output the intrinsic types. */
2205
2206 else
2207 {
2208 if (rep_ctr > 1)
2209 {
d30fe1c5 2210 snprintf(rep_buff, NML_DIGITS, " %d*", rep_ctr);
75b2dba9 2211 write_character (dtp, rep_buff, 1, strlen (rep_buff), NODELIM);
5e805e44 2212 dtp->u.p.no_leading_blank = 1;
29dc5138
PT
2213 }
2214 num++;
2215
420aa7b8 2216 /* Output the data, if an intrinsic type, or recurse into this
29dc5138
PT
2217 routine to treat derived types. */
2218
2219 switch (obj->type)
2220 {
2221
a11930ba 2222 case BT_INTEGER:
5e805e44 2223 write_integer (dtp, p, len);
6de9cd9a 2224 break;
29dc5138 2225
a11930ba 2226 case BT_LOGICAL:
5e805e44 2227 write_logical (dtp, p, len);
6de9cd9a 2228 break;
29dc5138 2229
a11930ba 2230 case BT_CHARACTER:
42c1e008
JD
2231 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
2232 write_character (dtp, p, 4, obj->string_length, DELIM);
2233 else
2234 write_character (dtp, p, 1, obj->string_length, DELIM);
6de9cd9a 2235 break;
29dc5138 2236
a11930ba 2237 case BT_REAL:
5e805e44 2238 write_real (dtp, p, len);
6de9cd9a 2239 break;
29dc5138 2240
a11930ba 2241 case BT_COMPLEX:
5e805e44 2242 dtp->u.p.no_leading_blank = 0;
29dc5138 2243 num++;
5e805e44 2244 write_complex (dtp, p, len, obj_size);
6de9cd9a 2245 break;
29dc5138 2246
a11930ba 2247 case BT_DERIVED:
e73d3ca6 2248 case BT_CLASS:
29dc5138
PT
2249 /* To treat a derived type, we need to build two strings:
2250 ext_name = the name, including qualifiers that prepends
420aa7b8 2251 component names in the output - passed to
29dc5138
PT
2252 nml_write_obj.
2253 obj_name = the derived type name with no qualifiers but %
420aa7b8 2254 appended. This is used to identify the
29dc5138
PT
2255 components. */
2256
2257 /* First ext_name => get length of all possible components */
e73d3ca6
PT
2258 if (obj->dtio_sub != NULL)
2259 {
2260 int unit = dtp->u.p.current_unit->unit_number;
2261 char iotype[] = "NAMELIST";
2262 gfc_charlen_type iotype_len = 8;
2263 char tmp_iomsg[IOMSG_LEN] = "";
2264 char *child_iomsg;
2265 gfc_charlen_type child_iomsg_len;
2266 int noiostat;
2267 int *child_iostat = NULL;
e9bfdf18 2268 gfc_full_array_i4 vlist;
e73d3ca6
PT
2269 formatted_dtio dtio_ptr = (formatted_dtio)obj->dtio_sub;
2270
2271 GFC_DIMENSION_SET(vlist.dim[0],1, 0, 0);
2272
e73d3ca6
PT
2273 /* Set iostat, intent(out). */
2274 noiostat = 0;
2275 child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
2276 dtp->common.iostat : &noiostat;
2277
2278 /* Set iomsg, intent(inout). */
2279 if (dtp->common.flags & IOPARM_HAS_IOMSG)
2280 {
2281 child_iomsg = dtp->common.iomsg;
2282 child_iomsg_len = dtp->common.iomsg_len;
2283 }
2284 else
2285 {
2286 child_iomsg = tmp_iomsg;
2287 child_iomsg_len = IOMSG_LEN;
2288 }
c08de9db 2289
e73d3ca6
PT
2290 /* Call the user defined formatted WRITE procedure. */
2291 dtp->u.p.current_unit->child_dtio++;
cf474530
JW
2292 if (obj->type == BT_DERIVED)
2293 {
a97de3cc 2294 /* Build a class container. */
cf474530
JW
2295 gfc_class list_obj;
2296 list_obj.data = p;
2297 list_obj.vptr = obj->vtable;
2298 list_obj.len = 0;
2299 dtio_ptr ((void *)&list_obj, &unit, iotype, &vlist,
2300 child_iostat, child_iomsg,
2301 iotype_len, child_iomsg_len);
2302 }
2303 else
2304 {
2305 dtio_ptr (p, &unit, iotype, &vlist,
2306 child_iostat, child_iomsg,
2307 iotype_len, child_iomsg_len);
2308 }
e73d3ca6
PT
2309 dtp->u.p.current_unit->child_dtio--;
2310
2311 goto obj_loop;
2312 }
29dc5138 2313
88fdfd5a
JB
2314 base_name_len = base_name ? strlen (base_name) : 0;
2315 base_var_name_len = base ? strlen (base->var_name) : 0;
e73d3ca6 2316 ext_name_len = base_name_len + base_var_name_len
d30fe1c5 2317 + strlen (obj->var_name) + obj->var_rank * NML_DIGITS + 1;
92e6f3a4 2318 ext_name = xmalloc (ext_name_len);
29dc5138 2319
76b88c5f
FXC
2320 if (base_name)
2321 memcpy (ext_name, base_name, base_name_len);
88fdfd5a 2322 clen = strlen (obj->var_name + base_var_name_len);
e73d3ca6 2323 memcpy (ext_name + base_name_len,
88fdfd5a 2324 obj->var_name + base_var_name_len, clen);
e73d3ca6 2325
29dc5138
PT
2326 /* Append the qualifier. */
2327
88fdfd5a 2328 tot_len = base_name_len + clen;
f9bfed22 2329 for (dim_i = 0; dim_i < (size_t) obj->var_rank; dim_i++)
29dc5138 2330 {
88fdfd5a
JB
2331 if (!dim_i)
2332 {
2333 ext_name[tot_len] = '(';
2334 tot_len++;
2335 }
e73d3ca6 2336 snprintf (ext_name + tot_len, ext_name_len - tot_len, "%d",
d30fe1c5 2337 (int) obj->ls[dim_i].idx);
88fdfd5a 2338 tot_len += strlen (ext_name + tot_len);
f9bfed22 2339 ext_name[tot_len] = ((int) dim_i == obj->var_rank - 1) ? ')' : ',';
88fdfd5a 2340 tot_len++;
29dc5138
PT
2341 }
2342
88fdfd5a 2343 ext_name[tot_len] = '\0';
9c5b1bf7
JD
2344 for (q = ext_name; *q; q++)
2345 if (*q == '+')
2346 *q = '%';
88fdfd5a 2347
29dc5138
PT
2348 /* Now obj_name. */
2349
2350 obj_name_len = strlen (obj->var_name) + 1;
92e6f3a4 2351 obj_name = xmalloc (obj_name_len + 1);
88fdfd5a
JB
2352 memcpy (obj_name, obj->var_name, obj_name_len-1);
2353 memcpy (obj_name + obj_name_len-1, "%", 2);
29dc5138
PT
2354
2355 /* Now loop over the components. Update the component pointer
2356 with the return value from nml_write_obj => this loop jumps
2357 past nested derived types. */
2358
2359 for (cmp = obj->next;
2360 cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
2361 cmp = retval)
2362 {
5e805e44
JJ
2363 retval = nml_write_obj (dtp, cmp,
2364 (index_type)(p - obj->mem_pos),
29dc5138
PT
2365 obj, ext_name);
2366 }
2367
bb408e87
JB
2368 free (obj_name);
2369 free (ext_name);
29dc5138
PT
2370 goto obj_loop;
2371
6de9cd9a 2372 default:
5e805e44 2373 internal_error (&dtp->common, "Bad type for namelist write");
6de9cd9a 2374 }
29dc5138 2375
10256cbe
JD
2376 /* Reset the leading blank suppression, write a comma (or semi-colon)
2377 and, if 5 values have been output, write a newline and advance
2378 to column 2. Reset the repeat counter. */
29dc5138 2379
5e805e44 2380 dtp->u.p.no_leading_blank = 0;
75b2dba9
JD
2381 if (obj->type == BT_CHARACTER)
2382 {
2383 if (dtp->u.p.nml_delim != '\0')
2384 write_character (dtp, &semi_comma, 1, 1, NODELIM);
2385 }
2386 else
2387 write_character (dtp, &semi_comma, 1, 1, NODELIM);
b10cf173
RS
2388 if (num > 5)
2389 {
2390 num = 0;
75b2dba9
JD
2391 if (dtp->u.p.nml_delim == '\0')
2392 write_character (dtp, &semi_comma, 1, 1, NODELIM);
8c8627c4 2393 namelist_write_newline (dtp);
75b2dba9 2394 write_character (dtp, " ", 1, 1, NODELIM);
29dc5138
PT
2395 }
2396 rep_ctr = 1;
2397 }
2398
2399 /* Cycle through and increment the index vector. */
2400
2401obj_loop:
2402
75b2dba9
JD
2403 nml_carry = 1;
2404 for (dim_i = 0; nml_carry && (dim_i < (size_t) obj->var_rank); dim_i++)
2405 {
2406 obj->ls[dim_i].idx += nml_carry ;
2407 nml_carry = 0;
2408 if (obj->ls[dim_i].idx > GFC_DESCRIPTOR_UBOUND(obj,dim_i))
2409 {
2410 obj->ls[dim_i].idx = GFC_DESCRIPTOR_LBOUND(obj,dim_i);
2411 nml_carry = 1;
2412 }
2413 }
29dc5138
PT
2414 }
2415
2416 /* Return a pointer beyond the furthest object accessed. */
2417
2418 return retval;
2419}
2420
8c8627c4 2421
29dc5138 2422/* This is the entry function for namelist writes. It outputs the name
420aa7b8
AJ
2423 of the namelist and iterates through the namelist by calls to
2424 nml_write_obj. The call below has dummys in the arguments used in
29dc5138
PT
2425 the treatment of derived types. */
2426
2427void
5e805e44 2428namelist_write (st_parameter_dt *dtp)
29dc5138 2429{
f29876bb 2430 namelist_info *t1, *t2, *dummy = NULL;
29dc5138
PT
2431 index_type dummy_offset = 0;
2432 char c;
f29876bb 2433 char *dummy_name = NULL;
29dc5138
PT
2434
2435 /* Set the delimiter for namelist output. */
75b2dba9
JD
2436 switch (dtp->u.p.current_unit->delim_status)
2437 {
2438 case DELIM_APOSTROPHE:
2439 dtp->u.p.nml_delim = '\'';
2440 break;
2441 case DELIM_QUOTE:
2442 case DELIM_UNSPECIFIED:
2443 dtp->u.p.nml_delim = '"';
2444 break;
2445 default:
2446 dtp->u.p.nml_delim = '\0';
2447 }
105b7136 2448
75b2dba9 2449 write_character (dtp, "&", 1, 1, NODELIM);
29dc5138
PT
2450
2451 /* Write namelist name in upper case - f95 std. */
f622221a 2452 for (gfc_charlen_type i = 0; i < dtp->namelist_name_len; i++ )
29dc5138 2453 {
21423a1d 2454 c = safe_toupper (dtp->namelist_name[i]);
75b2dba9 2455 write_character (dtp, &c, 1 ,1, NODELIM);
5e805e44 2456 }
29dc5138 2457
5e805e44 2458 if (dtp->u.p.ionml != NULL)
29dc5138 2459 {
5e805e44 2460 t1 = dtp->u.p.ionml;
29dc5138
PT
2461 while (t1 != NULL)
2462 {
2463 t2 = t1;
5e805e44 2464 t1 = nml_write_obj (dtp, t2, dummy_offset, dummy, dummy_name);
b10cf173
RS
2465 }
2466 }
0be72e3a 2467
8c8627c4 2468 namelist_write_newline (dtp);
75b2dba9 2469 write_character (dtp, " /", 1, 2, NODELIM);
6de9cd9a 2470}
29dc5138
PT
2471
2472#undef NML_DIGITS