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