re PR libfortran/41711 ([F08] BOZ edit-descr does not support reading large kind...
[gcc.git] / libgfortran / io / write.c
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
2 Free Software Foundation, Inc.
3 Contributed by Andy Vaught
4 Namelist output contributed by Paul Thomas
5 F2003 I/O support contributed by Jerry DeLisle
6
7 This file is part of the GNU Fortran 95 runtime library (libgfortran).
8
9 Libgfortran is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 Libgfortran is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 Under Section 7 of GPL version 3, you are granted additional
20 permissions described in the GCC Runtime Library Exception, version
21 3.1, as published by the Free Software Foundation.
22
23 You should have received a copy of the GNU General Public License and
24 a copy of the GCC Runtime Library Exception along with this program;
25 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26 <http://www.gnu.org/licenses/>. */
27
28 #include "io.h"
29 #include <assert.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <stdlib.h>
33 #include <stdbool.h>
34 #include <errno.h>
35 #define star_fill(p, n) memset(p, '*', n)
36
37 #include "write_float.def"
38
39 typedef unsigned char uchar;
40
41 /* Write out default char4. */
42
43 static void
44 write_default_char4 (st_parameter_dt *dtp, gfc_char4_t *source,
45 int src_len, int w_len)
46 {
47 char *p;
48 int j, k = 0;
49 gfc_char4_t c;
50 uchar d;
51
52 /* Take care of preceding blanks. */
53 if (w_len > src_len)
54 {
55 k = w_len - src_len;
56 p = write_block (dtp, k);
57 if (p == NULL)
58 return;
59 memset (p, ' ', k);
60 }
61
62 /* Get ready to handle delimiters if needed. */
63 switch (dtp->u.p.current_unit->delim_status)
64 {
65 case DELIM_APOSTROPHE:
66 d = '\'';
67 break;
68 case DELIM_QUOTE:
69 d = '"';
70 break;
71 default:
72 d = ' ';
73 break;
74 }
75
76 /* Now process the remaining characters, one at a time. */
77 for (j = k; j < src_len; j++)
78 {
79 c = source[j];
80
81 /* Handle delimiters if any. */
82 if (c == d && d != ' ')
83 {
84 p = write_block (dtp, 2);
85 if (p == NULL)
86 return;
87 *p++ = (uchar) c;
88 }
89 else
90 {
91 p = write_block (dtp, 1);
92 if (p == NULL)
93 return;
94 }
95 *p = c > 255 ? '?' : (uchar) c;
96 }
97 }
98
99
100 /* Write out UTF-8 converted from char4. */
101
102 static void
103 write_utf8_char4 (st_parameter_dt *dtp, gfc_char4_t *source,
104 int src_len, int w_len)
105 {
106 char *p;
107 int j, k = 0;
108 gfc_char4_t c;
109 static const uchar masks[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
110 static const uchar limits[6] = { 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
111 int nbytes;
112 uchar buf[6], d, *q;
113
114 /* Take care of preceding blanks. */
115 if (w_len > src_len)
116 {
117 k = w_len - src_len;
118 p = write_block (dtp, k);
119 if (p == NULL)
120 return;
121 memset (p, ' ', k);
122 }
123
124 /* Get ready to handle delimiters if needed. */
125 switch (dtp->u.p.current_unit->delim_status)
126 {
127 case DELIM_APOSTROPHE:
128 d = '\'';
129 break;
130 case DELIM_QUOTE:
131 d = '"';
132 break;
133 default:
134 d = ' ';
135 break;
136 }
137
138 /* Now process the remaining characters, one at a time. */
139 for (j = k; j < src_len; j++)
140 {
141 c = source[j];
142 if (c < 0x80)
143 {
144 /* Handle the delimiters if any. */
145 if (c == d && d != ' ')
146 {
147 p = write_block (dtp, 2);
148 if (p == NULL)
149 return;
150 *p++ = (uchar) c;
151 }
152 else
153 {
154 p = write_block (dtp, 1);
155 if (p == NULL)
156 return;
157 }
158 *p = (uchar) c;
159 }
160 else
161 {
162 /* Convert to UTF-8 sequence. */
163 nbytes = 1;
164 q = &buf[6];
165
166 do
167 {
168 *--q = ((c & 0x3F) | 0x80);
169 c >>= 6;
170 nbytes++;
171 }
172 while (c >= 0x3F || (c & limits[nbytes-1]));
173
174 *--q = (c | masks[nbytes-1]);
175
176 p = write_block (dtp, nbytes);
177 if (p == NULL)
178 return;
179
180 while (q < &buf[6])
181 *p++ = *q++;
182 }
183 }
184 }
185
186
187 void
188 write_a (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
189 {
190 int wlen;
191 char *p;
192
193 wlen = f->u.string.length < 0
194 || (f->format == FMT_G && f->u.string.length == 0)
195 ? len : f->u.string.length;
196
197 #ifdef HAVE_CRLF
198 /* If this is formatted STREAM IO convert any embedded line feed characters
199 to CR_LF on systems that use that sequence for newlines. See F2003
200 Standard sections 10.6.3 and 9.9 for further information. */
201 if (is_stream_io (dtp))
202 {
203 const char crlf[] = "\r\n";
204 int i, q, bytes;
205 q = bytes = 0;
206
207 /* Write out any padding if needed. */
208 if (len < wlen)
209 {
210 p = write_block (dtp, wlen - len);
211 if (p == NULL)
212 return;
213 memset (p, ' ', wlen - len);
214 }
215
216 /* Scan the source string looking for '\n' and convert it if found. */
217 for (i = 0; i < wlen; i++)
218 {
219 if (source[i] == '\n')
220 {
221 /* Write out the previously scanned characters in the string. */
222 if (bytes > 0)
223 {
224 p = write_block (dtp, bytes);
225 if (p == NULL)
226 return;
227 memcpy (p, &source[q], bytes);
228 q += bytes;
229 bytes = 0;
230 }
231
232 /* Write out the CR_LF sequence. */
233 q++;
234 p = write_block (dtp, 2);
235 if (p == NULL)
236 return;
237 memcpy (p, crlf, 2);
238 }
239 else
240 bytes++;
241 }
242
243 /* Write out any remaining bytes if no LF was found. */
244 if (bytes > 0)
245 {
246 p = write_block (dtp, bytes);
247 if (p == NULL)
248 return;
249 memcpy (p, &source[q], bytes);
250 }
251 }
252 else
253 {
254 #endif
255 p = write_block (dtp, wlen);
256 if (p == NULL)
257 return;
258
259 if (wlen < len)
260 memcpy (p, source, wlen);
261 else
262 {
263 memset (p, ' ', wlen - len);
264 memcpy (p + wlen - len, source, len);
265 }
266 #ifdef HAVE_CRLF
267 }
268 #endif
269 }
270
271
272 /* The primary difference between write_a_char4 and write_a is that we have to
273 deal with writing from the first byte of the 4-byte character and pay
274 attention to the most significant bytes. For ENCODING="default" write the
275 lowest significant byte. If the 3 most significant bytes contain
276 non-zero values, emit a '?'. For ENCODING="utf-8", convert the UCS-32 value
277 to the UTF-8 encoded string before writing out. */
278
279 void
280 write_a_char4 (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
281 {
282 int wlen;
283 gfc_char4_t *q;
284
285 wlen = f->u.string.length < 0
286 || (f->format == FMT_G && f->u.string.length == 0)
287 ? len : f->u.string.length;
288
289 q = (gfc_char4_t *) source;
290 #ifdef HAVE_CRLF
291 /* If this is formatted STREAM IO convert any embedded line feed characters
292 to CR_LF on systems that use that sequence for newlines. See F2003
293 Standard sections 10.6.3 and 9.9 for further information. */
294 if (is_stream_io (dtp))
295 {
296 const gfc_char4_t crlf[] = {0x000d,0x000a};
297 int i, bytes;
298 gfc_char4_t *qq;
299 bytes = 0;
300
301 /* Write out any padding if needed. */
302 if (len < wlen)
303 {
304 char *p;
305 p = write_block (dtp, wlen - len);
306 if (p == NULL)
307 return;
308 memset (p, ' ', wlen - len);
309 }
310
311 /* Scan the source string looking for '\n' and convert it if found. */
312 qq = (gfc_char4_t *) source;
313 for (i = 0; i < wlen; i++)
314 {
315 if (qq[i] == '\n')
316 {
317 /* Write out the previously scanned characters in the string. */
318 if (bytes > 0)
319 {
320 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
321 write_utf8_char4 (dtp, q, bytes, 0);
322 else
323 write_default_char4 (dtp, q, bytes, 0);
324 bytes = 0;
325 }
326
327 /* Write out the CR_LF sequence. */
328 write_default_char4 (dtp, crlf, 2, 0);
329 }
330 else
331 bytes++;
332 }
333
334 /* Write out any remaining bytes if no LF was found. */
335 if (bytes > 0)
336 {
337 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
338 write_utf8_char4 (dtp, q, bytes, 0);
339 else
340 write_default_char4 (dtp, q, bytes, 0);
341 }
342 }
343 else
344 {
345 #endif
346 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
347 write_utf8_char4 (dtp, q, len, wlen);
348 else
349 write_default_char4 (dtp, q, len, wlen);
350 #ifdef HAVE_CRLF
351 }
352 #endif
353 }
354
355
356 static GFC_INTEGER_LARGEST
357 extract_int (const void *p, int len)
358 {
359 GFC_INTEGER_LARGEST i = 0;
360
361 if (p == NULL)
362 return i;
363
364 switch (len)
365 {
366 case 1:
367 {
368 GFC_INTEGER_1 tmp;
369 memcpy ((void *) &tmp, p, len);
370 i = tmp;
371 }
372 break;
373 case 2:
374 {
375 GFC_INTEGER_2 tmp;
376 memcpy ((void *) &tmp, p, len);
377 i = tmp;
378 }
379 break;
380 case 4:
381 {
382 GFC_INTEGER_4 tmp;
383 memcpy ((void *) &tmp, p, len);
384 i = tmp;
385 }
386 break;
387 case 8:
388 {
389 GFC_INTEGER_8 tmp;
390 memcpy ((void *) &tmp, p, len);
391 i = tmp;
392 }
393 break;
394 #ifdef HAVE_GFC_INTEGER_16
395 case 16:
396 {
397 GFC_INTEGER_16 tmp;
398 memcpy ((void *) &tmp, p, len);
399 i = tmp;
400 }
401 break;
402 #endif
403 default:
404 internal_error (NULL, "bad integer kind");
405 }
406
407 return i;
408 }
409
410 static GFC_UINTEGER_LARGEST
411 extract_uint (const void *p, int len)
412 {
413 GFC_UINTEGER_LARGEST i = 0;
414
415 if (p == NULL)
416 return i;
417
418 switch (len)
419 {
420 case 1:
421 {
422 GFC_INTEGER_1 tmp;
423 memcpy ((void *) &tmp, p, len);
424 i = (GFC_UINTEGER_1) tmp;
425 }
426 break;
427 case 2:
428 {
429 GFC_INTEGER_2 tmp;
430 memcpy ((void *) &tmp, p, len);
431 i = (GFC_UINTEGER_2) tmp;
432 }
433 break;
434 case 4:
435 {
436 GFC_INTEGER_4 tmp;
437 memcpy ((void *) &tmp, p, len);
438 i = (GFC_UINTEGER_4) tmp;
439 }
440 break;
441 case 8:
442 {
443 GFC_INTEGER_8 tmp;
444 memcpy ((void *) &tmp, p, len);
445 i = (GFC_UINTEGER_8) tmp;
446 }
447 break;
448 #ifdef HAVE_GFC_INTEGER_16
449 case 10:
450 case 16:
451 {
452 GFC_INTEGER_16 tmp = 0;
453 memcpy ((void *) &tmp, p, len);
454 i = (GFC_UINTEGER_16) tmp;
455 }
456 break;
457 #endif
458 default:
459 internal_error (NULL, "bad integer kind");
460 }
461
462 return i;
463 }
464
465
466 void
467 write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
468 {
469 char *p;
470 int wlen;
471 GFC_INTEGER_LARGEST n;
472
473 wlen = (f->format == FMT_G && f->u.w == 0) ? 1 : f->u.w;
474
475 p = write_block (dtp, wlen);
476 if (p == NULL)
477 return;
478
479 memset (p, ' ', wlen - 1);
480 n = extract_int (source, len);
481 p[wlen - 1] = (n) ? 'T' : 'F';
482 }
483
484
485 static void
486 write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n)
487 {
488 int w, m, digits, nzero, nblank;
489 char *p;
490
491 w = f->u.integer.w;
492 m = f->u.integer.m;
493
494 /* Special case: */
495
496 if (m == 0 && n == 0)
497 {
498 if (w == 0)
499 w = 1;
500
501 p = write_block (dtp, w);
502 if (p == NULL)
503 return;
504
505 memset (p, ' ', w);
506 goto done;
507 }
508
509 digits = strlen (q);
510
511 /* Select a width if none was specified. The idea here is to always
512 print something. */
513
514 if (w == 0)
515 w = ((digits < m) ? m : digits);
516
517 p = write_block (dtp, w);
518 if (p == NULL)
519 return;
520
521 nzero = 0;
522 if (digits < m)
523 nzero = m - digits;
524
525 /* See if things will work. */
526
527 nblank = w - (nzero + digits);
528
529 if (nblank < 0)
530 {
531 star_fill (p, w);
532 goto done;
533 }
534
535 if (!dtp->u.p.no_leading_blank)
536 {
537 memset (p, ' ', nblank);
538 p += nblank;
539 memset (p, '0', nzero);
540 p += nzero;
541 memcpy (p, q, digits);
542 }
543 else
544 {
545 memset (p, '0', nzero);
546 p += nzero;
547 memcpy (p, q, digits);
548 p += digits;
549 memset (p, ' ', nblank);
550 dtp->u.p.no_leading_blank = 0;
551 }
552
553 done:
554 return;
555 }
556
557 static void
558 write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
559 int len,
560 const char *(*conv) (GFC_INTEGER_LARGEST, char *, size_t))
561 {
562 GFC_INTEGER_LARGEST n = 0;
563 int w, m, digits, nsign, nzero, nblank;
564 char *p;
565 const char *q;
566 sign_t sign;
567 char itoa_buf[GFC_BTOA_BUF_SIZE];
568
569 w = f->u.integer.w;
570 m = f->format == FMT_G ? -1 : f->u.integer.m;
571
572 n = extract_int (source, len);
573
574 /* Special case: */
575 if (m == 0 && n == 0)
576 {
577 if (w == 0)
578 w = 1;
579
580 p = write_block (dtp, w);
581 if (p == NULL)
582 return;
583
584 memset (p, ' ', w);
585 goto done;
586 }
587
588 sign = calculate_sign (dtp, n < 0);
589 if (n < 0)
590 n = -n;
591 nsign = sign == S_NONE ? 0 : 1;
592
593 /* conv calls itoa which sets the negative sign needed
594 by write_integer. The sign '+' or '-' is set below based on sign
595 calculated above, so we just point past the sign in the string
596 before proceeding to avoid double signs in corner cases.
597 (see PR38504) */
598 q = conv (n, itoa_buf, sizeof (itoa_buf));
599 if (*q == '-')
600 q++;
601
602 digits = strlen (q);
603
604 /* Select a width if none was specified. The idea here is to always
605 print something. */
606
607 if (w == 0)
608 w = ((digits < m) ? m : digits) + nsign;
609
610 p = write_block (dtp, w);
611 if (p == NULL)
612 return;
613
614 nzero = 0;
615 if (digits < m)
616 nzero = m - digits;
617
618 /* See if things will work. */
619
620 nblank = w - (nsign + nzero + digits);
621
622 if (nblank < 0)
623 {
624 star_fill (p, w);
625 goto done;
626 }
627
628 memset (p, ' ', nblank);
629 p += nblank;
630
631 switch (sign)
632 {
633 case S_PLUS:
634 *p++ = '+';
635 break;
636 case S_MINUS:
637 *p++ = '-';
638 break;
639 case S_NONE:
640 break;
641 }
642
643 memset (p, '0', nzero);
644 p += nzero;
645
646 memcpy (p, q, digits);
647
648 done:
649 return;
650 }
651
652
653 /* Convert unsigned octal to ascii. */
654
655 static const char *
656 otoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
657 {
658 char *p;
659
660 assert (len >= GFC_OTOA_BUF_SIZE);
661
662 if (n == 0)
663 return "0";
664
665 p = buffer + GFC_OTOA_BUF_SIZE - 1;
666 *p = '\0';
667
668 while (n != 0)
669 {
670 *--p = '0' + (n & 7);
671 n >>= 3;
672 }
673
674 return p;
675 }
676
677
678 /* Convert unsigned binary to ascii. */
679
680 static const char *
681 btoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
682 {
683 char *p;
684
685 assert (len >= GFC_BTOA_BUF_SIZE);
686
687 if (n == 0)
688 return "0";
689
690 p = buffer + GFC_BTOA_BUF_SIZE - 1;
691 *p = '\0';
692
693 while (n != 0)
694 {
695 *--p = '0' + (n & 1);
696 n >>= 1;
697 }
698
699 return p;
700 }
701
702 /* The following three functions, btoa_big, otoa_big, and ztoa_big, are needed
703 to convert large reals with kind sizes that exceed the largest integer type
704 available on certain platforms. In these cases, byte by byte conversion is
705 performed. Endianess is taken into account. */
706
707 /* Conversion to binary. */
708
709 static const char *
710 btoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
711 {
712 char *q;
713 int i, j;
714
715 q = buffer;
716 if (big_endian)
717 {
718 const char *p = s;
719 for (i = 0; i < len; i++)
720 {
721 char c = *p;
722
723 /* Test for zero. Needed by write_boz later. */
724 if (*p != 0)
725 *n = 1;
726
727 for (j = 0; j < 8; j++)
728 {
729 *q++ = (c & 128) ? '1' : '0';
730 c <<= 1;
731 }
732 p++;
733 }
734 }
735 else
736 {
737 const char *p = s + len - 1;
738 for (i = 0; i < len; i++)
739 {
740 char c = *p;
741
742 /* Test for zero. Needed by write_boz later. */
743 if (*p != 0)
744 *n = 1;
745
746 for (j = 0; j < 8; j++)
747 {
748 *q++ = (c & 128) ? '1' : '0';
749 c <<= 1;
750 }
751 p--;
752 }
753 }
754
755 *q = '\0';
756
757 if (*n == 0)
758 return "0";
759
760 /* Move past any leading zeros. */
761 while (*buffer == '0')
762 buffer++;
763
764 return buffer;
765
766 }
767
768 /* Conversion to octal. */
769
770 static const char *
771 otoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
772 {
773 char *q;
774 int i, j, k;
775 uint8_t octet;
776
777 q = buffer + GFC_OTOA_BUF_SIZE - 1;
778 *q = '\0';
779 i = k = octet = 0;
780
781 if (big_endian)
782 {
783 const char *p = s + len - 1;
784 char c = *p;
785 while (i < len)
786 {
787 /* Test for zero. Needed by write_boz later. */
788 if (*p != 0)
789 *n = 1;
790
791 for (j = 0; j < 3 && i < len; j++)
792 {
793 octet |= (c & 1) << j;
794 c >>= 1;
795 if (++k > 7)
796 {
797 i++;
798 k = 0;
799 c = *--p;
800 }
801 }
802 *--q = '0' + octet;
803 octet = 0;
804 }
805 }
806 else
807 {
808 const char *p = s;
809 char c = *p;
810 while (i < len)
811 {
812 /* Test for zero. Needed by write_boz later. */
813 if (*p != 0)
814 *n = 1;
815
816 for (j = 0; j < 3 && i < len; j++)
817 {
818 octet |= (c & 1) << j;
819 c >>= 1;
820 if (++k > 7)
821 {
822 i++;
823 k = 0;
824 c = *++p;
825 }
826 }
827 *--q = '0' + octet;
828 octet = 0;
829 }
830 }
831
832 if (*n == 0)
833 return "0";
834
835 /* Move past any leading zeros. */
836 while (*q == '0')
837 q++;
838
839 return q;
840 }
841
842 /* Conversion to hexidecimal. */
843
844 static const char *
845 ztoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
846 {
847 static char a[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
848 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
849
850 char *q;
851 uint8_t h, l;
852 int i;
853
854 q = buffer;
855
856 if (big_endian)
857 {
858 const char *p = s;
859 for (i = 0; i < len; i++)
860 {
861 /* Test for zero. Needed by write_boz later. */
862 if (*p != 0)
863 *n = 1;
864
865 h = (*p >> 4) & 0x0F;
866 l = *p++ & 0x0F;
867 *q++ = a[h];
868 *q++ = a[l];
869 }
870 }
871 else
872 {
873 const char *p = s + len - 1;
874 for (i = 0; i < len; i++)
875 {
876 /* Test for zero. Needed by write_boz later. */
877 if (*p != 0)
878 *n = 1;
879
880 h = (*p >> 4) & 0x0F;
881 l = *p-- & 0x0F;
882 *q++ = a[h];
883 *q++ = a[l];
884 }
885 }
886
887 *q = '\0';
888
889 if (*n == 0)
890 return "0";
891
892 /* Move past any leading zeros. */
893 while (*buffer == '0')
894 buffer++;
895
896 return buffer;
897 }
898
899 /* gfc_itoa()-- Integer to decimal conversion.
900 The itoa function is a widespread non-standard extension to standard
901 C, often declared in <stdlib.h>. Even though the itoa defined here
902 is a static function we take care not to conflict with any prior
903 non-static declaration. Hence the 'gfc_' prefix, which is normally
904 reserved for functions with external linkage. */
905
906 static const char *
907 gfc_itoa (GFC_INTEGER_LARGEST n, char *buffer, size_t len)
908 {
909 int negative;
910 char *p;
911 GFC_UINTEGER_LARGEST t;
912
913 assert (len >= GFC_ITOA_BUF_SIZE);
914
915 if (n == 0)
916 return "0";
917
918 negative = 0;
919 t = n;
920 if (n < 0)
921 {
922 negative = 1;
923 t = -n; /*must use unsigned to protect from overflow*/
924 }
925
926 p = buffer + GFC_ITOA_BUF_SIZE - 1;
927 *p = '\0';
928
929 while (t != 0)
930 {
931 *--p = '0' + (t % 10);
932 t /= 10;
933 }
934
935 if (negative)
936 *--p = '-';
937 return p;
938 }
939
940
941 void
942 write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
943 {
944 write_decimal (dtp, f, p, len, (void *) gfc_itoa);
945 }
946
947
948 void
949 write_b (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
950 {
951 const char *p;
952 char itoa_buf[GFC_BTOA_BUF_SIZE];
953 GFC_UINTEGER_LARGEST n = 0;
954
955 if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
956 {
957 p = btoa_big (source, itoa_buf, len, &n);
958 write_boz (dtp, f, p, n);
959 }
960 else
961 {
962 n = extract_uint (source, len);
963 p = btoa (n, itoa_buf, sizeof (itoa_buf));
964 write_boz (dtp, f, p, n);
965 }
966 }
967
968
969 void
970 write_o (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
971 {
972 const char *p;
973 char itoa_buf[GFC_OTOA_BUF_SIZE];
974 GFC_UINTEGER_LARGEST n = 0;
975
976 if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
977 {
978 p = otoa_big (source, itoa_buf, len, &n);
979 write_boz (dtp, f, p, n);
980 }
981 else
982 {
983 n = extract_uint (source, len);
984 p = otoa (n, itoa_buf, sizeof (itoa_buf));
985 write_boz (dtp, f, p, n);
986 }
987 }
988
989 void
990 write_z (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
991 {
992 const char *p;
993 char itoa_buf[GFC_XTOA_BUF_SIZE];
994 GFC_UINTEGER_LARGEST n = 0;
995
996 if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
997 {
998 p = ztoa_big (source, itoa_buf, len, &n);
999 write_boz (dtp, f, p, n);
1000 }
1001 else
1002 {
1003 n = extract_uint (source, len);
1004 p = gfc_xtoa (n, itoa_buf, sizeof (itoa_buf));
1005 write_boz (dtp, f, p, n);
1006 }
1007 }
1008
1009
1010 void
1011 write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1012 {
1013 write_float (dtp, f, p, len);
1014 }
1015
1016
1017 void
1018 write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1019 {
1020 write_float (dtp, f, p, len);
1021 }
1022
1023
1024 void
1025 write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1026 {
1027 write_float (dtp, f, p, len);
1028 }
1029
1030
1031 void
1032 write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1033 {
1034 write_float (dtp, f, p, len);
1035 }
1036
1037
1038 void
1039 write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1040 {
1041 write_float (dtp, f, p, len);
1042 }
1043
1044
1045 /* Take care of the X/TR descriptor. */
1046
1047 void
1048 write_x (st_parameter_dt *dtp, int len, int nspaces)
1049 {
1050 char *p;
1051
1052 p = write_block (dtp, len);
1053 if (p == NULL)
1054 return;
1055 if (nspaces > 0 && len - nspaces >= 0)
1056 memset (&p[len - nspaces], ' ', nspaces);
1057 }
1058
1059
1060 /* List-directed writing. */
1061
1062
1063 /* Write a single character to the output. Returns nonzero if
1064 something goes wrong. */
1065
1066 static int
1067 write_char (st_parameter_dt *dtp, char c)
1068 {
1069 char *p;
1070
1071 p = write_block (dtp, 1);
1072 if (p == NULL)
1073 return 1;
1074
1075 *p = c;
1076
1077 return 0;
1078 }
1079
1080
1081 /* Write a list-directed logical value. */
1082
1083 static void
1084 write_logical (st_parameter_dt *dtp, const char *source, int length)
1085 {
1086 write_char (dtp, extract_int (source, length) ? 'T' : 'F');
1087 }
1088
1089
1090 /* Write a list-directed integer value. */
1091
1092 static void
1093 write_integer (st_parameter_dt *dtp, const char *source, int length)
1094 {
1095 char *p;
1096 const char *q;
1097 int digits;
1098 int width;
1099 char itoa_buf[GFC_ITOA_BUF_SIZE];
1100
1101 q = gfc_itoa (extract_int (source, length), itoa_buf, sizeof (itoa_buf));
1102
1103 switch (length)
1104 {
1105 case 1:
1106 width = 4;
1107 break;
1108
1109 case 2:
1110 width = 6;
1111 break;
1112
1113 case 4:
1114 width = 11;
1115 break;
1116
1117 case 8:
1118 width = 20;
1119 break;
1120
1121 default:
1122 width = 0;
1123 break;
1124 }
1125
1126 digits = strlen (q);
1127
1128 if (width < digits)
1129 width = digits;
1130 p = write_block (dtp, width);
1131 if (p == NULL)
1132 return;
1133 if (dtp->u.p.no_leading_blank)
1134 {
1135 memcpy (p, q, digits);
1136 memset (p + digits, ' ', width - digits);
1137 }
1138 else
1139 {
1140 memset (p, ' ', width - digits);
1141 memcpy (p + width - digits, q, digits);
1142 }
1143 }
1144
1145
1146 /* Write a list-directed string. We have to worry about delimiting
1147 the strings if the file has been opened in that mode. */
1148
1149 static void
1150 write_character (st_parameter_dt *dtp, const char *source, int kind, int length)
1151 {
1152 int i, extra;
1153 char *p, d;
1154
1155 switch (dtp->u.p.current_unit->delim_status)
1156 {
1157 case DELIM_APOSTROPHE:
1158 d = '\'';
1159 break;
1160 case DELIM_QUOTE:
1161 d = '"';
1162 break;
1163 default:
1164 d = ' ';
1165 break;
1166 }
1167
1168 if (kind == 1)
1169 {
1170 if (d == ' ')
1171 extra = 0;
1172 else
1173 {
1174 extra = 2;
1175
1176 for (i = 0; i < length; i++)
1177 if (source[i] == d)
1178 extra++;
1179 }
1180
1181 p = write_block (dtp, length + extra);
1182 if (p == NULL)
1183 return;
1184
1185 if (d == ' ')
1186 memcpy (p, source, length);
1187 else
1188 {
1189 *p++ = d;
1190
1191 for (i = 0; i < length; i++)
1192 {
1193 *p++ = source[i];
1194 if (source[i] == d)
1195 *p++ = d;
1196 }
1197
1198 *p = d;
1199 }
1200 }
1201 else
1202 {
1203 if (d == ' ')
1204 {
1205 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
1206 write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
1207 else
1208 write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
1209 }
1210 else
1211 {
1212 p = write_block (dtp, 1);
1213 *p = d;
1214
1215 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
1216 write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
1217 else
1218 write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
1219
1220 p = write_block (dtp, 1);
1221 *p = d;
1222 }
1223 }
1224 }
1225
1226
1227 /* Set an fnode to default format. */
1228
1229 static void
1230 set_fnode_default (st_parameter_dt *dtp, fnode *f, int length)
1231 {
1232 f->format = FMT_G;
1233 switch (length)
1234 {
1235 case 4:
1236 f->u.real.w = 15;
1237 f->u.real.d = 8;
1238 f->u.real.e = 2;
1239 break;
1240 case 8:
1241 f->u.real.w = 25;
1242 f->u.real.d = 17;
1243 f->u.real.e = 3;
1244 break;
1245 case 10:
1246 f->u.real.w = 29;
1247 f->u.real.d = 20;
1248 f->u.real.e = 4;
1249 break;
1250 case 16:
1251 f->u.real.w = 44;
1252 f->u.real.d = 35;
1253 f->u.real.e = 4;
1254 break;
1255 default:
1256 internal_error (&dtp->common, "bad real kind");
1257 break;
1258 }
1259 }
1260 /* Output a real number with default format.
1261 This is 1PG14.7E2 for REAL(4), 1PG23.15E3 for REAL(8),
1262 1PG28.19E4 for REAL(10) and 1PG43.34E4 for REAL(16). */
1263
1264 void
1265 write_real (st_parameter_dt *dtp, const char *source, int length)
1266 {
1267 fnode f ;
1268 int org_scale = dtp->u.p.scale_factor;
1269 dtp->u.p.scale_factor = 1;
1270 set_fnode_default (dtp, &f, length);
1271 write_float (dtp, &f, source , length);
1272 dtp->u.p.scale_factor = org_scale;
1273 }
1274
1275
1276 void
1277 write_real_g0 (st_parameter_dt *dtp, const char *source, int length, int d)
1278 {
1279 fnode f ;
1280 set_fnode_default (dtp, &f, length);
1281 if (d > 0)
1282 f.u.real.d = d;
1283 dtp->u.p.g0_no_blanks = 1;
1284 write_float (dtp, &f, source , length);
1285 dtp->u.p.g0_no_blanks = 0;
1286 }
1287
1288
1289 static void
1290 write_complex (st_parameter_dt *dtp, const char *source, int kind, size_t size)
1291 {
1292 char semi_comma =
1293 dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';';
1294
1295 if (write_char (dtp, '('))
1296 return;
1297 write_real (dtp, source, kind);
1298
1299 if (write_char (dtp, semi_comma))
1300 return;
1301 write_real (dtp, source + size / 2, kind);
1302
1303 write_char (dtp, ')');
1304 }
1305
1306
1307 /* Write the separator between items. */
1308
1309 static void
1310 write_separator (st_parameter_dt *dtp)
1311 {
1312 char *p;
1313
1314 p = write_block (dtp, options.separator_len);
1315 if (p == NULL)
1316 return;
1317
1318 memcpy (p, options.separator, options.separator_len);
1319 }
1320
1321
1322 /* Write an item with list formatting.
1323 TODO: handle skipping to the next record correctly, particularly
1324 with strings. */
1325
1326 static void
1327 list_formatted_write_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
1328 size_t size)
1329 {
1330 if (dtp->u.p.current_unit == NULL)
1331 return;
1332
1333 if (dtp->u.p.first_item)
1334 {
1335 dtp->u.p.first_item = 0;
1336 write_char (dtp, ' ');
1337 }
1338 else
1339 {
1340 if (type != BT_CHARACTER || !dtp->u.p.char_flag ||
1341 dtp->u.p.current_unit->delim_status != DELIM_NONE)
1342 write_separator (dtp);
1343 }
1344
1345 switch (type)
1346 {
1347 case BT_INTEGER:
1348 write_integer (dtp, p, kind);
1349 break;
1350 case BT_LOGICAL:
1351 write_logical (dtp, p, kind);
1352 break;
1353 case BT_CHARACTER:
1354 write_character (dtp, p, kind, size);
1355 break;
1356 case BT_REAL:
1357 write_real (dtp, p, kind);
1358 break;
1359 case BT_COMPLEX:
1360 write_complex (dtp, p, kind, size);
1361 break;
1362 default:
1363 internal_error (&dtp->common, "list_formatted_write(): Bad type");
1364 }
1365
1366 dtp->u.p.char_flag = (type == BT_CHARACTER);
1367 }
1368
1369
1370 void
1371 list_formatted_write (st_parameter_dt *dtp, bt type, void *p, int kind,
1372 size_t size, size_t nelems)
1373 {
1374 size_t elem;
1375 char *tmp;
1376 size_t stride = type == BT_CHARACTER ?
1377 size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
1378
1379 tmp = (char *) p;
1380
1381 /* Big loop over all the elements. */
1382 for (elem = 0; elem < nelems; elem++)
1383 {
1384 dtp->u.p.item_count++;
1385 list_formatted_write_scalar (dtp, type, tmp + elem * stride, kind, size);
1386 }
1387 }
1388
1389 /* NAMELIST OUTPUT
1390
1391 nml_write_obj writes a namelist object to the output stream. It is called
1392 recursively for derived type components:
1393 obj = is the namelist_info for the current object.
1394 offset = the offset relative to the address held by the object for
1395 derived type arrays.
1396 base = is the namelist_info of the derived type, when obj is a
1397 component.
1398 base_name = the full name for a derived type, including qualifiers
1399 if any.
1400 The returned value is a pointer to the object beyond the last one
1401 accessed, including nested derived types. Notice that the namelist is
1402 a linear linked list of objects, including derived types and their
1403 components. A tree, of sorts, is implied by the compound names of
1404 the derived type components and this is how this function recurses through
1405 the list. */
1406
1407 /* A generous estimate of the number of characters needed to print
1408 repeat counts and indices, including commas, asterices and brackets. */
1409
1410 #define NML_DIGITS 20
1411
1412 static void
1413 namelist_write_newline (st_parameter_dt *dtp)
1414 {
1415 if (!is_internal_unit (dtp))
1416 {
1417 #ifdef HAVE_CRLF
1418 write_character (dtp, "\r\n", 1, 2);
1419 #else
1420 write_character (dtp, "\n", 1, 1);
1421 #endif
1422 return;
1423 }
1424
1425 if (is_array_io (dtp))
1426 {
1427 gfc_offset record;
1428 int finished, length;
1429
1430 length = (int) dtp->u.p.current_unit->bytes_left;
1431
1432 /* Now that the current record has been padded out,
1433 determine where the next record in the array is. */
1434 record = next_array_record (dtp, dtp->u.p.current_unit->ls,
1435 &finished);
1436 if (finished)
1437 dtp->u.p.current_unit->endfile = AT_ENDFILE;
1438 else
1439 {
1440 /* Now seek to this record */
1441 record = record * dtp->u.p.current_unit->recl;
1442
1443 if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
1444 {
1445 generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
1446 return;
1447 }
1448
1449 dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
1450 }
1451 }
1452 else
1453 write_character (dtp, " ", 1, 1);
1454 }
1455
1456
1457 static namelist_info *
1458 nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
1459 namelist_info * base, char * base_name)
1460 {
1461 int rep_ctr;
1462 int num;
1463 int nml_carry;
1464 int len;
1465 index_type obj_size;
1466 index_type nelem;
1467 size_t dim_i;
1468 size_t clen;
1469 index_type elem_ctr;
1470 size_t obj_name_len;
1471 void * p ;
1472 char cup;
1473 char * obj_name;
1474 char * ext_name;
1475 char rep_buff[NML_DIGITS];
1476 namelist_info * cmp;
1477 namelist_info * retval = obj->next;
1478 size_t base_name_len;
1479 size_t base_var_name_len;
1480 size_t tot_len;
1481 unit_delim tmp_delim;
1482
1483 /* Set the character to be used to separate values
1484 to a comma or semi-colon. */
1485
1486 char semi_comma =
1487 dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';';
1488
1489 /* Write namelist variable names in upper case. If a derived type,
1490 nothing is output. If a component, base and base_name are set. */
1491
1492 if (obj->type != GFC_DTYPE_DERIVED)
1493 {
1494 namelist_write_newline (dtp);
1495 write_character (dtp, " ", 1, 1);
1496
1497 len = 0;
1498 if (base)
1499 {
1500 len = strlen (base->var_name);
1501 base_name_len = strlen (base_name);
1502 for (dim_i = 0; dim_i < base_name_len; dim_i++)
1503 {
1504 cup = toupper (base_name[dim_i]);
1505 write_character (dtp, &cup, 1, 1);
1506 }
1507 }
1508 clen = strlen (obj->var_name);
1509 for (dim_i = len; dim_i < clen; dim_i++)
1510 {
1511 cup = toupper (obj->var_name[dim_i]);
1512 write_character (dtp, &cup, 1, 1);
1513 }
1514 write_character (dtp, "=", 1, 1);
1515 }
1516
1517 /* Counts the number of data output on a line, including names. */
1518
1519 num = 1;
1520
1521 len = obj->len;
1522
1523 switch (obj->type)
1524 {
1525
1526 case GFC_DTYPE_REAL:
1527 obj_size = size_from_real_kind (len);
1528 break;
1529
1530 case GFC_DTYPE_COMPLEX:
1531 obj_size = size_from_complex_kind (len);
1532 break;
1533
1534 case GFC_DTYPE_CHARACTER:
1535 obj_size = obj->string_length;
1536 break;
1537
1538 default:
1539 obj_size = len;
1540 }
1541
1542 if (obj->var_rank)
1543 obj_size = obj->size;
1544
1545 /* Set the index vector and count the number of elements. */
1546
1547 nelem = 1;
1548 for (dim_i = 0; dim_i < (size_t) obj->var_rank; dim_i++)
1549 {
1550 obj->ls[dim_i].idx = GFC_DESCRIPTOR_LBOUND(obj, dim_i);
1551 nelem = nelem * GFC_DESCRIPTOR_EXTENT (obj, dim_i);
1552 }
1553
1554 /* Main loop to output the data held in the object. */
1555
1556 rep_ctr = 1;
1557 for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
1558 {
1559
1560 /* Build the pointer to the data value. The offset is passed by
1561 recursive calls to this function for arrays of derived types.
1562 Is NULL otherwise. */
1563
1564 p = (void *)(obj->mem_pos + elem_ctr * obj_size);
1565 p += offset;
1566
1567 /* Check for repeat counts of intrinsic types. */
1568
1569 if ((elem_ctr < (nelem - 1)) &&
1570 (obj->type != GFC_DTYPE_DERIVED) &&
1571 !memcmp (p, (void*)(p + obj_size ), obj_size ))
1572 {
1573 rep_ctr++;
1574 }
1575
1576 /* Execute a repeated output. Note the flag no_leading_blank that
1577 is used in the functions used to output the intrinsic types. */
1578
1579 else
1580 {
1581 if (rep_ctr > 1)
1582 {
1583 sprintf(rep_buff, " %d*", rep_ctr);
1584 write_character (dtp, rep_buff, 1, strlen (rep_buff));
1585 dtp->u.p.no_leading_blank = 1;
1586 }
1587 num++;
1588
1589 /* Output the data, if an intrinsic type, or recurse into this
1590 routine to treat derived types. */
1591
1592 switch (obj->type)
1593 {
1594
1595 case GFC_DTYPE_INTEGER:
1596 write_integer (dtp, p, len);
1597 break;
1598
1599 case GFC_DTYPE_LOGICAL:
1600 write_logical (dtp, p, len);
1601 break;
1602
1603 case GFC_DTYPE_CHARACTER:
1604 tmp_delim = dtp->u.p.current_unit->delim_status;
1605 if (dtp->u.p.nml_delim == '"')
1606 dtp->u.p.current_unit->delim_status = DELIM_QUOTE;
1607 if (dtp->u.p.nml_delim == '\'')
1608 dtp->u.p.current_unit->delim_status = DELIM_APOSTROPHE;
1609 write_character (dtp, p, 1, obj->string_length);
1610 dtp->u.p.current_unit->delim_status = tmp_delim;
1611 break;
1612
1613 case GFC_DTYPE_REAL:
1614 write_real (dtp, p, len);
1615 break;
1616
1617 case GFC_DTYPE_COMPLEX:
1618 dtp->u.p.no_leading_blank = 0;
1619 num++;
1620 write_complex (dtp, p, len, obj_size);
1621 break;
1622
1623 case GFC_DTYPE_DERIVED:
1624
1625 /* To treat a derived type, we need to build two strings:
1626 ext_name = the name, including qualifiers that prepends
1627 component names in the output - passed to
1628 nml_write_obj.
1629 obj_name = the derived type name with no qualifiers but %
1630 appended. This is used to identify the
1631 components. */
1632
1633 /* First ext_name => get length of all possible components */
1634
1635 base_name_len = base_name ? strlen (base_name) : 0;
1636 base_var_name_len = base ? strlen (base->var_name) : 0;
1637 ext_name = (char*)get_mem ( base_name_len
1638 + base_var_name_len
1639 + strlen (obj->var_name)
1640 + obj->var_rank * NML_DIGITS
1641 + 1);
1642
1643 memcpy (ext_name, base_name, base_name_len);
1644 clen = strlen (obj->var_name + base_var_name_len);
1645 memcpy (ext_name + base_name_len,
1646 obj->var_name + base_var_name_len, clen);
1647
1648 /* Append the qualifier. */
1649
1650 tot_len = base_name_len + clen;
1651 for (dim_i = 0; dim_i < (size_t) obj->var_rank; dim_i++)
1652 {
1653 if (!dim_i)
1654 {
1655 ext_name[tot_len] = '(';
1656 tot_len++;
1657 }
1658 sprintf (ext_name + tot_len, "%d", (int) obj->ls[dim_i].idx);
1659 tot_len += strlen (ext_name + tot_len);
1660 ext_name[tot_len] = ((int) dim_i == obj->var_rank - 1) ? ')' : ',';
1661 tot_len++;
1662 }
1663
1664 ext_name[tot_len] = '\0';
1665
1666 /* Now obj_name. */
1667
1668 obj_name_len = strlen (obj->var_name) + 1;
1669 obj_name = get_mem (obj_name_len+1);
1670 memcpy (obj_name, obj->var_name, obj_name_len-1);
1671 memcpy (obj_name + obj_name_len-1, "%", 2);
1672
1673 /* Now loop over the components. Update the component pointer
1674 with the return value from nml_write_obj => this loop jumps
1675 past nested derived types. */
1676
1677 for (cmp = obj->next;
1678 cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
1679 cmp = retval)
1680 {
1681 retval = nml_write_obj (dtp, cmp,
1682 (index_type)(p - obj->mem_pos),
1683 obj, ext_name);
1684 }
1685
1686 free_mem (obj_name);
1687 free_mem (ext_name);
1688 goto obj_loop;
1689
1690 default:
1691 internal_error (&dtp->common, "Bad type for namelist write");
1692 }
1693
1694 /* Reset the leading blank suppression, write a comma (or semi-colon)
1695 and, if 5 values have been output, write a newline and advance
1696 to column 2. Reset the repeat counter. */
1697
1698 dtp->u.p.no_leading_blank = 0;
1699 write_character (dtp, &semi_comma, 1, 1);
1700 if (num > 5)
1701 {
1702 num = 0;
1703 namelist_write_newline (dtp);
1704 write_character (dtp, " ", 1, 1);
1705 }
1706 rep_ctr = 1;
1707 }
1708
1709 /* Cycle through and increment the index vector. */
1710
1711 obj_loop:
1712
1713 nml_carry = 1;
1714 for (dim_i = 0; nml_carry && (dim_i < (size_t) obj->var_rank); dim_i++)
1715 {
1716 obj->ls[dim_i].idx += nml_carry ;
1717 nml_carry = 0;
1718 if (obj->ls[dim_i].idx > (ssize_t) GFC_DESCRIPTOR_UBOUND(obj,dim_i))
1719 {
1720 obj->ls[dim_i].idx = GFC_DESCRIPTOR_LBOUND(obj,dim_i);
1721 nml_carry = 1;
1722 }
1723 }
1724 }
1725
1726 /* Return a pointer beyond the furthest object accessed. */
1727
1728 return retval;
1729 }
1730
1731
1732 /* This is the entry function for namelist writes. It outputs the name
1733 of the namelist and iterates through the namelist by calls to
1734 nml_write_obj. The call below has dummys in the arguments used in
1735 the treatment of derived types. */
1736
1737 void
1738 namelist_write (st_parameter_dt *dtp)
1739 {
1740 namelist_info * t1, *t2, *dummy = NULL;
1741 index_type i;
1742 index_type dummy_offset = 0;
1743 char c;
1744 char * dummy_name = NULL;
1745 unit_delim tmp_delim = DELIM_UNSPECIFIED;
1746
1747 /* Set the delimiter for namelist output. */
1748 tmp_delim = dtp->u.p.current_unit->delim_status;
1749
1750 dtp->u.p.nml_delim = tmp_delim == DELIM_APOSTROPHE ? '\'' : '"';
1751
1752 /* Temporarily disable namelist delimters. */
1753 dtp->u.p.current_unit->delim_status = DELIM_NONE;
1754
1755 write_character (dtp, "&", 1, 1);
1756
1757 /* Write namelist name in upper case - f95 std. */
1758 for (i = 0 ;i < dtp->namelist_name_len ;i++ )
1759 {
1760 c = toupper (dtp->namelist_name[i]);
1761 write_character (dtp, &c, 1 ,1);
1762 }
1763
1764 if (dtp->u.p.ionml != NULL)
1765 {
1766 t1 = dtp->u.p.ionml;
1767 while (t1 != NULL)
1768 {
1769 t2 = t1;
1770 t1 = nml_write_obj (dtp, t2, dummy_offset, dummy, dummy_name);
1771 }
1772 }
1773
1774 namelist_write_newline (dtp);
1775 write_character (dtp, " /", 1, 2);
1776 /* Restore the original delimiter. */
1777 dtp->u.p.current_unit->delim_status = tmp_delim;
1778 }
1779
1780 #undef NML_DIGITS