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