re PR libfortran/35863 ([F2003] Implement ENCODING="UTF-8")
[gcc.git] / libgfortran / io / write.c
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
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 2, or (at your option)
12 any later version.
13
14 In addition to the permissions in the GNU General Public License, the
15 Free Software Foundation gives you unlimited permission to link the
16 compiled version of this file into combinations with other programs,
17 and to distribute those combinations without any restriction coming
18 from the use of this file. (The General Public License restrictions
19 do apply in other respects; for example, they cover modification of
20 the file, and distribution when not linked into a combine
21 executable.)
22
23 Libgfortran is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
27
28 You should have received a copy of the GNU General Public License
29 along with Libgfortran; see the file COPYING. If not, write to
30 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
31 Boston, MA 02110-1301, USA. */
32
33 #include "io.h"
34 #include <assert.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <stdbool.h>
39 #include <errno.h>
40 #define star_fill(p, n) memset(p, '*', n)
41
42 #include "write_float.def"
43
44 typedef unsigned char uchar;
45
46 /* Write out default char4. */
47
48 static void
49 write_default_char4 (st_parameter_dt *dtp, gfc_char4_t *source,
50 int src_len, int w_len)
51 {
52 char *p;
53 int j, k = 0;
54 gfc_char4_t c;
55 uchar d;
56
57 /* Take care of preceding blanks. */
58 if (w_len > src_len)
59 {
60 k = w_len - src_len;
61 p = write_block (dtp, k);
62 if (p == NULL)
63 return;
64 memset (p, ' ', k);
65 }
66
67 /* Get ready to handle delimiters if needed. */
68
69 switch (dtp->u.p.delim_status)
70 {
71 case DELIM_APOSTROPHE:
72 d = '\'';
73 break;
74 case DELIM_QUOTE:
75 d = '"';
76 break;
77 default:
78 d = ' ';
79 break;
80 }
81
82 /* Now process the remaining characters, one at a time. */
83 for (j = k; j < src_len; j++)
84 {
85 c = source[j];
86
87 /* Handle delimiters if any. */
88 if (c == d && d != ' ')
89 {
90 p = write_block (dtp, 2);
91 if (p == NULL)
92 return;
93 *p++ = (uchar) c;
94 }
95 else
96 {
97 p = write_block (dtp, 1);
98 if (p == NULL)
99 return;
100 }
101 *p = c > 255 ? '?' : (uchar) c;
102 }
103 }
104
105
106 /* Write out UTF-8 converted from char4. */
107
108 static void
109 write_utf8_char4 (st_parameter_dt *dtp, gfc_char4_t *source,
110 int src_len, int w_len)
111 {
112 char *p;
113 int j, k = 0;
114 gfc_char4_t c;
115 static const uchar masks[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
116 static const uchar limits[6] = { 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
117 size_t nbytes;
118 uchar buf[6], d, *q;
119
120 /* Take care of preceding blanks. */
121 if (w_len > src_len)
122 {
123 k = w_len - src_len;
124 p = write_block (dtp, k);
125 if (p == NULL)
126 return;
127 memset (p, ' ', k);
128 }
129
130 /* Get ready to handle delimiters if needed. */
131
132 switch (dtp->u.p.delim_status)
133 {
134 case DELIM_APOSTROPHE:
135 d = '\'';
136 break;
137 case DELIM_QUOTE:
138 d = '"';
139 break;
140 default:
141 d = ' ';
142 break;
143 }
144
145 /* Now process the remaining characters, one at a time. */
146 for (j = k; j < src_len; j++)
147 {
148 c = source[j];
149 if (c < 0x80)
150 {
151 /* Handle the delimiters if any. */
152 if (c == d && d != ' ')
153 {
154 p = write_block (dtp, 2);
155 if (p == NULL)
156 return;
157 *p++ = (uchar) c;
158 }
159 else
160 {
161 p = write_block (dtp, 1);
162 if (p == NULL)
163 return;
164 }
165 *p = (uchar) c;
166 }
167 else
168 {
169 /* Convert to UTF-8 sequence. */
170 nbytes = 1;
171 q = &buf[6];
172
173 do
174 {
175 *--q = ((c & 0x3F) | 0x80);
176 c >>= 6;
177 nbytes++;
178 }
179 while (c >= 0x3F || (c & limits[nbytes-1]));
180
181 *--q = (c | masks[nbytes-1]);
182
183 p = write_block (dtp, nbytes);
184 if (p == NULL)
185 return;
186
187 while (q < &buf[6])
188 *p++ = *q++;
189 }
190 }
191 }
192
193
194 void
195 write_a (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
196 {
197 int wlen;
198 char *p;
199
200 wlen = f->u.string.length < 0
201 || (f->format == FMT_G && f->u.string.length == 0)
202 ? len : f->u.string.length;
203
204 #ifdef HAVE_CRLF
205 /* If this is formatted STREAM IO convert any embedded line feed characters
206 to CR_LF on systems that use that sequence for newlines. See F2003
207 Standard sections 10.6.3 and 9.9 for further information. */
208 if (is_stream_io (dtp))
209 {
210 const char crlf[] = "\r\n";
211 int i, q, bytes;
212 q = bytes = 0;
213
214 /* Write out any padding if needed. */
215 if (len < wlen)
216 {
217 p = write_block (dtp, wlen - len);
218 if (p == NULL)
219 return;
220 memset (p, ' ', wlen - len);
221 }
222
223 /* Scan the source string looking for '\n' and convert it if found. */
224 for (i = 0; i < wlen; i++)
225 {
226 if (source[i] == '\n')
227 {
228 /* Write out the previously scanned characters in the string. */
229 if (bytes > 0)
230 {
231 p = write_block (dtp, bytes);
232 if (p == NULL)
233 return;
234 memcpy (p, &source[q], bytes);
235 q += bytes;
236 bytes = 0;
237 }
238
239 /* Write out the CR_LF sequence. */
240 q++;
241 p = write_block (dtp, 2);
242 if (p == NULL)
243 return;
244 memcpy (p, crlf, 2);
245 }
246 else
247 bytes++;
248 }
249
250 /* Write out any remaining bytes if no LF was found. */
251 if (bytes > 0)
252 {
253 p = write_block (dtp, bytes);
254 if (p == NULL)
255 return;
256 memcpy (p, &source[q], bytes);
257 }
258 }
259 else
260 {
261 #endif
262 p = write_block (dtp, wlen);
263 if (p == NULL)
264 return;
265
266 if (wlen < len)
267 memcpy (p, source, wlen);
268 else
269 {
270 memset (p, ' ', wlen - len);
271 memcpy (p + wlen - len, source, len);
272 }
273 #ifdef HAVE_CRLF
274 }
275 #endif
276 }
277
278
279 /* The primary difference between write_a_char4 and write_a is that we have to
280 deal with writing from the first byte of the 4-byte character and pay
281 attention to the most significant bytes. For ENCODING="default" write the
282 lowest significant byte. If the 3 most significant bytes contain
283 non-zero values, emit a '?'. For ENCODING="utf-8", convert the UCS-32 value
284 to the UTF-8 encoded string before writing out. */
285
286 void
287 write_a_char4 (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
288 {
289 int wlen;
290 gfc_char4_t *q;
291
292 wlen = f->u.string.length < 0
293 || (f->format == FMT_G && f->u.string.length == 0)
294 ? len : f->u.string.length;
295
296 q = (gfc_char4_t *) source;
297 #ifdef HAVE_CRLF
298 /* If this is formatted STREAM IO convert any embedded line feed characters
299 to CR_LF on systems that use that sequence for newlines. See F2003
300 Standard sections 10.6.3 and 9.9 for further information. */
301 if (is_stream_io (dtp))
302 {
303 const char crlf[] = "\r\n";
304 int i, j, bytes;
305 gfc_char4_t *qq;
306 bytes = 0;
307
308 /* Write out any padding if needed. */
309 if (len < wlen)
310 {
311 char *p;
312 p = write_block (dtp, wlen - len);
313 if (p == NULL)
314 return;
315 memset (p, ' ', wlen - len);
316 }
317
318 /* Scan the source string looking for '\n' and convert it if found. */
319 qq = (gfc_char4_t *) source;
320 for (i = 0; i < wlen; i++)
321 {
322 if (qq[i] == '\n')
323 {
324 /* Write out the previously scanned characters in the string. */
325 if (bytes > 0)
326 {
327 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
328 write_utf8_char4 (dtp, q, bytes, 0);
329 else
330 write_default_char4 (dtp, q, bytes, 0);
331 bytes = 0;
332 }
333
334 /* Write out the CR_LF sequence. */
335 write_default_char4 (dtp, crlf, 2, 0);
336 }
337 else
338 bytes++;
339 }
340
341 /* Write out any remaining bytes if no LF was found. */
342 if (bytes > 0)
343 {
344 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
345 write_utf8_char4 (dtp, q, bytes, 0);
346 else
347 write_default_char4 (dtp, q, bytes, 0);
348 }
349 }
350 else
351 {
352 #endif
353 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
354 write_utf8_char4 (dtp, q, len, wlen);
355 else
356 write_default_char4 (dtp, q, len, wlen);
357 #ifdef HAVE_CRLF
358 }
359 #endif
360 }
361
362
363 static GFC_INTEGER_LARGEST
364 extract_int (const void *p, int len)
365 {
366 GFC_INTEGER_LARGEST i = 0;
367
368 if (p == NULL)
369 return i;
370
371 switch (len)
372 {
373 case 1:
374 {
375 GFC_INTEGER_1 tmp;
376 memcpy ((void *) &tmp, p, len);
377 i = tmp;
378 }
379 break;
380 case 2:
381 {
382 GFC_INTEGER_2 tmp;
383 memcpy ((void *) &tmp, p, len);
384 i = tmp;
385 }
386 break;
387 case 4:
388 {
389 GFC_INTEGER_4 tmp;
390 memcpy ((void *) &tmp, p, len);
391 i = tmp;
392 }
393 break;
394 case 8:
395 {
396 GFC_INTEGER_8 tmp;
397 memcpy ((void *) &tmp, p, len);
398 i = tmp;
399 }
400 break;
401 #ifdef HAVE_GFC_INTEGER_16
402 case 16:
403 {
404 GFC_INTEGER_16 tmp;
405 memcpy ((void *) &tmp, p, len);
406 i = tmp;
407 }
408 break;
409 #endif
410 default:
411 internal_error (NULL, "bad integer kind");
412 }
413
414 return i;
415 }
416
417 static GFC_UINTEGER_LARGEST
418 extract_uint (const void *p, int len)
419 {
420 GFC_UINTEGER_LARGEST i = 0;
421
422 if (p == NULL)
423 return i;
424
425 switch (len)
426 {
427 case 1:
428 {
429 GFC_INTEGER_1 tmp;
430 memcpy ((void *) &tmp, p, len);
431 i = (GFC_UINTEGER_1) tmp;
432 }
433 break;
434 case 2:
435 {
436 GFC_INTEGER_2 tmp;
437 memcpy ((void *) &tmp, p, len);
438 i = (GFC_UINTEGER_2) tmp;
439 }
440 break;
441 case 4:
442 {
443 GFC_INTEGER_4 tmp;
444 memcpy ((void *) &tmp, p, len);
445 i = (GFC_UINTEGER_4) tmp;
446 }
447 break;
448 case 8:
449 {
450 GFC_INTEGER_8 tmp;
451 memcpy ((void *) &tmp, p, len);
452 i = (GFC_UINTEGER_8) tmp;
453 }
454 break;
455 #ifdef HAVE_GFC_INTEGER_16
456 case 16:
457 {
458 GFC_INTEGER_16 tmp;
459 memcpy ((void *) &tmp, p, len);
460 i = (GFC_UINTEGER_16) tmp;
461 }
462 break;
463 #endif
464 default:
465 internal_error (NULL, "bad integer kind");
466 }
467
468 return i;
469 }
470
471
472 void
473 write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
474 {
475 char *p;
476 int wlen;
477 GFC_INTEGER_LARGEST n;
478
479 wlen = (f->format == FMT_G && f->u.w == 0) ? 1 : f->u.w;
480
481 p = write_block (dtp, wlen);
482 if (p == NULL)
483 return;
484
485 memset (p, ' ', wlen - 1);
486 n = extract_int (source, len);
487 p[wlen - 1] = (n) ? 'T' : 'F';
488 }
489
490
491 static void
492 write_int (st_parameter_dt *dtp, const fnode *f, const char *source, int len,
493 const char *(*conv) (GFC_UINTEGER_LARGEST, char *, size_t))
494 {
495 GFC_UINTEGER_LARGEST n = 0;
496 int w, m, digits, nzero, nblank;
497 char *p;
498 const char *q;
499 char itoa_buf[GFC_BTOA_BUF_SIZE];
500
501 w = f->u.integer.w;
502 m = f->u.integer.m;
503
504 n = extract_uint (source, len);
505
506 /* Special case: */
507
508 if (m == 0 && n == 0)
509 {
510 if (w == 0)
511 w = 1;
512
513 p = write_block (dtp, w);
514 if (p == NULL)
515 return;
516
517 memset (p, ' ', w);
518 goto done;
519 }
520
521 q = conv (n, itoa_buf, sizeof (itoa_buf));
522 digits = strlen (q);
523
524 /* Select a width if none was specified. The idea here is to always
525 print something. */
526
527 if (w == 0)
528 w = ((digits < m) ? m : digits);
529
530 p = write_block (dtp, w);
531 if (p == NULL)
532 return;
533
534 nzero = 0;
535 if (digits < m)
536 nzero = m - digits;
537
538 /* See if things will work. */
539
540 nblank = w - (nzero + digits);
541
542 if (nblank < 0)
543 {
544 star_fill (p, w);
545 goto done;
546 }
547
548
549 if (!dtp->u.p.no_leading_blank)
550 {
551 memset (p, ' ', nblank);
552 p += nblank;
553 memset (p, '0', nzero);
554 p += nzero;
555 memcpy (p, q, digits);
556 }
557 else
558 {
559 memset (p, '0', nzero);
560 p += nzero;
561 memcpy (p, q, digits);
562 p += digits;
563 memset (p, ' ', nblank);
564 dtp->u.p.no_leading_blank = 0;
565 }
566
567 done:
568 return;
569 }
570
571 static void
572 write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
573 int len,
574 const char *(*conv) (GFC_INTEGER_LARGEST, char *, size_t))
575 {
576 GFC_INTEGER_LARGEST n = 0;
577 int w, m, digits, nsign, nzero, nblank;
578 char *p;
579 const char *q;
580 sign_t sign;
581 char itoa_buf[GFC_BTOA_BUF_SIZE];
582
583 w = f->u.integer.w;
584 m = f->format == FMT_G ? -1 : f->u.integer.m;
585
586 n = extract_int (source, len);
587
588 /* Special case: */
589 if (m == 0 && n == 0)
590 {
591 if (w == 0)
592 w = 1;
593
594 p = write_block (dtp, w);
595 if (p == NULL)
596 return;
597
598 memset (p, ' ', w);
599 goto done;
600 }
601
602 sign = calculate_sign (dtp, n < 0);
603 if (n < 0)
604 n = -n;
605
606 nsign = sign == S_NONE ? 0 : 1;
607 q = conv (n, itoa_buf, sizeof (itoa_buf));
608
609 digits = strlen (q);
610
611 /* Select a width if none was specified. The idea here is to always
612 print something. */
613
614 if (w == 0)
615 w = ((digits < m) ? m : digits) + nsign;
616
617 p = write_block (dtp, w);
618 if (p == NULL)
619 return;
620
621 nzero = 0;
622 if (digits < m)
623 nzero = m - digits;
624
625 /* See if things will work. */
626
627 nblank = w - (nsign + nzero + digits);
628
629 if (nblank < 0)
630 {
631 star_fill (p, w);
632 goto done;
633 }
634
635 memset (p, ' ', nblank);
636 p += nblank;
637
638 switch (sign)
639 {
640 case S_PLUS:
641 *p++ = '+';
642 break;
643 case S_MINUS:
644 *p++ = '-';
645 break;
646 case S_NONE:
647 break;
648 }
649
650 memset (p, '0', nzero);
651 p += nzero;
652
653 memcpy (p, q, digits);
654
655 done:
656 return;
657 }
658
659
660 /* Convert unsigned octal to ascii. */
661
662 static const char *
663 otoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
664 {
665 char *p;
666
667 assert (len >= GFC_OTOA_BUF_SIZE);
668
669 if (n == 0)
670 return "0";
671
672 p = buffer + GFC_OTOA_BUF_SIZE - 1;
673 *p = '\0';
674
675 while (n != 0)
676 {
677 *--p = '0' + (n & 7);
678 n >>= 3;
679 }
680
681 return p;
682 }
683
684
685 /* Convert unsigned binary to ascii. */
686
687 static const char *
688 btoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
689 {
690 char *p;
691
692 assert (len >= GFC_BTOA_BUF_SIZE);
693
694 if (n == 0)
695 return "0";
696
697 p = buffer + GFC_BTOA_BUF_SIZE - 1;
698 *p = '\0';
699
700 while (n != 0)
701 {
702 *--p = '0' + (n & 1);
703 n >>= 1;
704 }
705
706 return p;
707 }
708
709
710 void
711 write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
712 {
713 write_decimal (dtp, f, p, len, (void *) gfc_itoa);
714 }
715
716
717 void
718 write_b (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
719 {
720 write_int (dtp, f, p, len, btoa);
721 }
722
723
724 void
725 write_o (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
726 {
727 write_int (dtp, f, p, len, otoa);
728 }
729
730 void
731 write_z (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
732 {
733 write_int (dtp, f, p, len, xtoa);
734 }
735
736
737 void
738 write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
739 {
740 write_float (dtp, f, p, len);
741 }
742
743
744 void
745 write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
746 {
747 write_float (dtp, f, p, len);
748 }
749
750
751 void
752 write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
753 {
754 write_float (dtp, f, p, len);
755 }
756
757
758 void
759 write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
760 {
761 write_float (dtp, f, p, len);
762 }
763
764
765 void
766 write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
767 {
768 write_float (dtp, f, p, len);
769 }
770
771
772 /* Take care of the X/TR descriptor. */
773
774 void
775 write_x (st_parameter_dt *dtp, int len, int nspaces)
776 {
777 char *p;
778
779 p = write_block (dtp, len);
780 if (p == NULL)
781 return;
782
783 if (nspaces > 0)
784 memset (&p[len - nspaces], ' ', nspaces);
785 }
786
787
788 /* List-directed writing. */
789
790
791 /* Write a single character to the output. Returns nonzero if
792 something goes wrong. */
793
794 static int
795 write_char (st_parameter_dt *dtp, char c)
796 {
797 char *p;
798
799 p = write_block (dtp, 1);
800 if (p == NULL)
801 return 1;
802
803 *p = c;
804
805 return 0;
806 }
807
808
809 /* Write a list-directed logical value. */
810
811 static void
812 write_logical (st_parameter_dt *dtp, const char *source, int length)
813 {
814 write_char (dtp, extract_int (source, length) ? 'T' : 'F');
815 }
816
817
818 /* Write a list-directed integer value. */
819
820 static void
821 write_integer (st_parameter_dt *dtp, const char *source, int length)
822 {
823 char *p;
824 const char *q;
825 int digits;
826 int width;
827 char itoa_buf[GFC_ITOA_BUF_SIZE];
828
829 q = gfc_itoa (extract_int (source, length), itoa_buf, sizeof (itoa_buf));
830
831 switch (length)
832 {
833 case 1:
834 width = 4;
835 break;
836
837 case 2:
838 width = 6;
839 break;
840
841 case 4:
842 width = 11;
843 break;
844
845 case 8:
846 width = 20;
847 break;
848
849 default:
850 width = 0;
851 break;
852 }
853
854 digits = strlen (q);
855
856 if (width < digits)
857 width = digits;
858 p = write_block (dtp, width);
859 if (p == NULL)
860 return;
861 if (dtp->u.p.no_leading_blank)
862 {
863 memcpy (p, q, digits);
864 memset (p + digits, ' ', width - digits);
865 }
866 else
867 {
868 memset (p, ' ', width - digits);
869 memcpy (p + width - digits, q, digits);
870 }
871 }
872
873
874 /* Write a list-directed string. We have to worry about delimiting
875 the strings if the file has been opened in that mode. */
876
877 static void
878 write_character (st_parameter_dt *dtp, const char *source, int kind, int length)
879 {
880 int i, extra;
881 char *p, d;
882
883 switch (dtp->u.p.delim_status)
884 {
885 case DELIM_APOSTROPHE:
886 d = '\'';
887 break;
888 case DELIM_QUOTE:
889 d = '"';
890 break;
891 default:
892 d = ' ';
893 break;
894 }
895
896 if (kind == 1)
897 {
898 if (d == ' ')
899 extra = 0;
900 else
901 {
902 extra = 2;
903
904 for (i = 0; i < length; i++)
905 if (source[i] == d)
906 extra++;
907 }
908
909 p = write_block (dtp, length + extra);
910 if (p == NULL)
911 return;
912
913 if (d == ' ')
914 memcpy (p, source, length);
915 else
916 {
917 *p++ = d;
918
919 for (i = 0; i < length; i++)
920 {
921 *p++ = source[i];
922 if (source[i] == d)
923 *p++ = d;
924 }
925
926 *p = d;
927 }
928 }
929 else
930 {
931 if (d == ' ')
932 {
933 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
934 write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
935 else
936 write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
937 }
938 else
939 {
940 p = write_block (dtp, 1);
941 *p = d;
942
943 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
944 write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
945 else
946 write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
947
948 p = write_block (dtp, 1);
949 *p = d;
950 }
951 }
952 }
953
954
955 /* Output a real number with default format.
956 This is 1PG14.7E2 for REAL(4), 1PG23.15E3 for REAL(8),
957 1PG28.19E4 for REAL(10) and 1PG43.34E4 for REAL(16). */
958
959 void
960 write_real (st_parameter_dt *dtp, const char *source, int length)
961 {
962 fnode f ;
963 int org_scale = dtp->u.p.scale_factor;
964 f.format = FMT_G;
965 dtp->u.p.scale_factor = 1;
966 switch (length)
967 {
968 case 4:
969 f.u.real.w = 15;
970 f.u.real.d = 8;
971 f.u.real.e = 2;
972 break;
973 case 8:
974 f.u.real.w = 25;
975 f.u.real.d = 17;
976 f.u.real.e = 3;
977 break;
978 case 10:
979 f.u.real.w = 29;
980 f.u.real.d = 20;
981 f.u.real.e = 4;
982 break;
983 case 16:
984 f.u.real.w = 44;
985 f.u.real.d = 35;
986 f.u.real.e = 4;
987 break;
988 default:
989 internal_error (&dtp->common, "bad real kind");
990 break;
991 }
992 write_float (dtp, &f, source , length);
993 dtp->u.p.scale_factor = org_scale;
994 }
995
996
997 static void
998 write_complex (st_parameter_dt *dtp, const char *source, int kind, size_t size)
999 {
1000 char semi_comma = dtp->u.p.decimal_status == DECIMAL_POINT ? ',' : ';';
1001
1002 if (write_char (dtp, '('))
1003 return;
1004 write_real (dtp, source, kind);
1005
1006 if (write_char (dtp, semi_comma))
1007 return;
1008 write_real (dtp, source + size / 2, kind);
1009
1010 write_char (dtp, ')');
1011 }
1012
1013
1014 /* Write the separator between items. */
1015
1016 static void
1017 write_separator (st_parameter_dt *dtp)
1018 {
1019 char *p;
1020
1021 p = write_block (dtp, options.separator_len);
1022 if (p == NULL)
1023 return;
1024
1025 memcpy (p, options.separator, options.separator_len);
1026 }
1027
1028
1029 /* Write an item with list formatting.
1030 TODO: handle skipping to the next record correctly, particularly
1031 with strings. */
1032
1033 static void
1034 list_formatted_write_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
1035 size_t size)
1036 {
1037 if (dtp->u.p.current_unit == NULL)
1038 return;
1039
1040 if (dtp->u.p.first_item)
1041 {
1042 dtp->u.p.first_item = 0;
1043 write_char (dtp, ' ');
1044 }
1045 else
1046 {
1047 if (type != BT_CHARACTER || !dtp->u.p.char_flag ||
1048 dtp->u.p.delim_status != DELIM_NONE)
1049 write_separator (dtp);
1050 }
1051
1052 switch (type)
1053 {
1054 case BT_INTEGER:
1055 write_integer (dtp, p, kind);
1056 break;
1057 case BT_LOGICAL:
1058 write_logical (dtp, p, kind);
1059 break;
1060 case BT_CHARACTER:
1061 write_character (dtp, p, kind, size);
1062 break;
1063 case BT_REAL:
1064 write_real (dtp, p, kind);
1065 break;
1066 case BT_COMPLEX:
1067 write_complex (dtp, p, kind, size);
1068 break;
1069 default:
1070 internal_error (&dtp->common, "list_formatted_write(): Bad type");
1071 }
1072
1073 dtp->u.p.char_flag = (type == BT_CHARACTER);
1074 }
1075
1076
1077 void
1078 list_formatted_write (st_parameter_dt *dtp, bt type, void *p, int kind,
1079 size_t size, size_t nelems)
1080 {
1081 size_t elem;
1082 char *tmp;
1083 size_t stride = type == BT_CHARACTER ?
1084 size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
1085
1086 tmp = (char *) p;
1087
1088 /* Big loop over all the elements. */
1089 for (elem = 0; elem < nelems; elem++)
1090 {
1091 dtp->u.p.item_count++;
1092 list_formatted_write_scalar (dtp, type, tmp + elem * stride, kind, size);
1093 }
1094 }
1095
1096 /* NAMELIST OUTPUT
1097
1098 nml_write_obj writes a namelist object to the output stream. It is called
1099 recursively for derived type components:
1100 obj = is the namelist_info for the current object.
1101 offset = the offset relative to the address held by the object for
1102 derived type arrays.
1103 base = is the namelist_info of the derived type, when obj is a
1104 component.
1105 base_name = the full name for a derived type, including qualifiers
1106 if any.
1107 The returned value is a pointer to the object beyond the last one
1108 accessed, including nested derived types. Notice that the namelist is
1109 a linear linked list of objects, including derived types and their
1110 components. A tree, of sorts, is implied by the compound names of
1111 the derived type components and this is how this function recurses through
1112 the list. */
1113
1114 /* A generous estimate of the number of characters needed to print
1115 repeat counts and indices, including commas, asterices and brackets. */
1116
1117 #define NML_DIGITS 20
1118
1119 static namelist_info *
1120 nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
1121 namelist_info * base, char * base_name)
1122 {
1123 int rep_ctr;
1124 int num;
1125 int nml_carry;
1126 index_type len;
1127 index_type obj_size;
1128 index_type nelem;
1129 index_type dim_i;
1130 index_type clen;
1131 index_type elem_ctr;
1132 index_type obj_name_len;
1133 void * p ;
1134 char cup;
1135 char * obj_name;
1136 char * ext_name;
1137 char rep_buff[NML_DIGITS];
1138 namelist_info * cmp;
1139 namelist_info * retval = obj->next;
1140 size_t base_name_len;
1141 size_t base_var_name_len;
1142 size_t tot_len;
1143 unit_delim tmp_delim;
1144
1145 /* Set the character to be used to separate values
1146 to a comma or semi-colon. */
1147
1148 char semi_comma = dtp->u.p.decimal_status == DECIMAL_POINT ? ',' : ';';
1149
1150 /* Write namelist variable names in upper case. If a derived type,
1151 nothing is output. If a component, base and base_name are set. */
1152
1153 if (obj->type != GFC_DTYPE_DERIVED)
1154 {
1155 #ifdef HAVE_CRLF
1156 write_character (dtp, "\r\n ", 1, 3);
1157 #else
1158 write_character (dtp, "\n ", 1, 2);
1159 #endif
1160 len = 0;
1161 if (base)
1162 {
1163 len =strlen (base->var_name);
1164 for (dim_i = 0; dim_i < (index_type) strlen (base_name); dim_i++)
1165 {
1166 cup = toupper (base_name[dim_i]);
1167 write_character (dtp, &cup, 1, 1);
1168 }
1169 }
1170 for (dim_i =len; dim_i < (index_type) strlen (obj->var_name); dim_i++)
1171 {
1172 cup = toupper (obj->var_name[dim_i]);
1173 write_character (dtp, &cup, 1, 1);
1174 }
1175 write_character (dtp, "=", 1, 1);
1176 }
1177
1178 /* Counts the number of data output on a line, including names. */
1179
1180 num = 1;
1181
1182 len = obj->len;
1183
1184 switch (obj->type)
1185 {
1186
1187 case GFC_DTYPE_REAL:
1188 obj_size = size_from_real_kind (len);
1189 break;
1190
1191 case GFC_DTYPE_COMPLEX:
1192 obj_size = size_from_complex_kind (len);
1193 break;
1194
1195 case GFC_DTYPE_CHARACTER:
1196 obj_size = obj->string_length;
1197 break;
1198
1199 default:
1200 obj_size = len;
1201 }
1202
1203 if (obj->var_rank)
1204 obj_size = obj->size;
1205
1206 /* Set the index vector and count the number of elements. */
1207
1208 nelem = 1;
1209 for (dim_i=0; dim_i < obj->var_rank; dim_i++)
1210 {
1211 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1212 nelem = nelem * (obj->dim[dim_i].ubound + 1 - obj->dim[dim_i].lbound);
1213 }
1214
1215 /* Main loop to output the data held in the object. */
1216
1217 rep_ctr = 1;
1218 for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
1219 {
1220
1221 /* Build the pointer to the data value. The offset is passed by
1222 recursive calls to this function for arrays of derived types.
1223 Is NULL otherwise. */
1224
1225 p = (void *)(obj->mem_pos + elem_ctr * obj_size);
1226 p += offset;
1227
1228 /* Check for repeat counts of intrinsic types. */
1229
1230 if ((elem_ctr < (nelem - 1)) &&
1231 (obj->type != GFC_DTYPE_DERIVED) &&
1232 !memcmp (p, (void*)(p + obj_size ), obj_size ))
1233 {
1234 rep_ctr++;
1235 }
1236
1237 /* Execute a repeated output. Note the flag no_leading_blank that
1238 is used in the functions used to output the intrinsic types. */
1239
1240 else
1241 {
1242 if (rep_ctr > 1)
1243 {
1244 sprintf(rep_buff, " %d*", rep_ctr);
1245 write_character (dtp, rep_buff, 1, strlen (rep_buff));
1246 dtp->u.p.no_leading_blank = 1;
1247 }
1248 num++;
1249
1250 /* Output the data, if an intrinsic type, or recurse into this
1251 routine to treat derived types. */
1252
1253 switch (obj->type)
1254 {
1255
1256 case GFC_DTYPE_INTEGER:
1257 write_integer (dtp, p, len);
1258 break;
1259
1260 case GFC_DTYPE_LOGICAL:
1261 write_logical (dtp, p, len);
1262 break;
1263
1264 case GFC_DTYPE_CHARACTER:
1265 tmp_delim = dtp->u.p.delim_status;
1266 if (dtp->u.p.nml_delim == '"')
1267 dtp->u.p.delim_status = DELIM_QUOTE;
1268 if (dtp->u.p.nml_delim == '\'')
1269 dtp->u.p.delim_status = DELIM_APOSTROPHE;
1270 write_character (dtp, p, 1, obj->string_length);
1271 dtp->u.p.delim_status = tmp_delim;
1272 break;
1273
1274 case GFC_DTYPE_REAL:
1275 write_real (dtp, p, len);
1276 break;
1277
1278 case GFC_DTYPE_COMPLEX:
1279 dtp->u.p.no_leading_blank = 0;
1280 num++;
1281 write_complex (dtp, p, len, obj_size);
1282 break;
1283
1284 case GFC_DTYPE_DERIVED:
1285
1286 /* To treat a derived type, we need to build two strings:
1287 ext_name = the name, including qualifiers that prepends
1288 component names in the output - passed to
1289 nml_write_obj.
1290 obj_name = the derived type name with no qualifiers but %
1291 appended. This is used to identify the
1292 components. */
1293
1294 /* First ext_name => get length of all possible components */
1295
1296 base_name_len = base_name ? strlen (base_name) : 0;
1297 base_var_name_len = base ? strlen (base->var_name) : 0;
1298 ext_name = (char*)get_mem ( base_name_len
1299 + base_var_name_len
1300 + strlen (obj->var_name)
1301 + obj->var_rank * NML_DIGITS
1302 + 1);
1303
1304 memcpy (ext_name, base_name, base_name_len);
1305 clen = strlen (obj->var_name + base_var_name_len);
1306 memcpy (ext_name + base_name_len,
1307 obj->var_name + base_var_name_len, clen);
1308
1309 /* Append the qualifier. */
1310
1311 tot_len = base_name_len + clen;
1312 for (dim_i = 0; dim_i < obj->var_rank; dim_i++)
1313 {
1314 if (!dim_i)
1315 {
1316 ext_name[tot_len] = '(';
1317 tot_len++;
1318 }
1319 sprintf (ext_name + tot_len, "%d", (int) obj->ls[dim_i].idx);
1320 tot_len += strlen (ext_name + tot_len);
1321 ext_name[tot_len] = (dim_i == obj->var_rank - 1) ? ')' : ',';
1322 tot_len++;
1323 }
1324
1325 ext_name[tot_len] = '\0';
1326
1327 /* Now obj_name. */
1328
1329 obj_name_len = strlen (obj->var_name) + 1;
1330 obj_name = get_mem (obj_name_len+1);
1331 memcpy (obj_name, obj->var_name, obj_name_len-1);
1332 memcpy (obj_name + obj_name_len-1, "%", 2);
1333
1334 /* Now loop over the components. Update the component pointer
1335 with the return value from nml_write_obj => this loop jumps
1336 past nested derived types. */
1337
1338 for (cmp = obj->next;
1339 cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
1340 cmp = retval)
1341 {
1342 retval = nml_write_obj (dtp, cmp,
1343 (index_type)(p - obj->mem_pos),
1344 obj, ext_name);
1345 }
1346
1347 free_mem (obj_name);
1348 free_mem (ext_name);
1349 goto obj_loop;
1350
1351 default:
1352 internal_error (&dtp->common, "Bad type for namelist write");
1353 }
1354
1355 /* Reset the leading blank suppression, write a comma (or semi-colon)
1356 and, if 5 values have been output, write a newline and advance
1357 to column 2. Reset the repeat counter. */
1358
1359 dtp->u.p.no_leading_blank = 0;
1360 write_character (dtp, &semi_comma, 1, 1);
1361 if (num > 5)
1362 {
1363 num = 0;
1364 #ifdef HAVE_CRLF
1365 write_character (dtp, "\r\n ", 1, 3);
1366 #else
1367 write_character (dtp, "\n ", 1, 2);
1368 #endif
1369 }
1370 rep_ctr = 1;
1371 }
1372
1373 /* Cycle through and increment the index vector. */
1374
1375 obj_loop:
1376
1377 nml_carry = 1;
1378 for (dim_i = 0; nml_carry && (dim_i < obj->var_rank); dim_i++)
1379 {
1380 obj->ls[dim_i].idx += nml_carry ;
1381 nml_carry = 0;
1382 if (obj->ls[dim_i].idx > (ssize_t)obj->dim[dim_i].ubound)
1383 {
1384 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1385 nml_carry = 1;
1386 }
1387 }
1388 }
1389
1390 /* Return a pointer beyond the furthest object accessed. */
1391
1392 return retval;
1393 }
1394
1395 /* This is the entry function for namelist writes. It outputs the name
1396 of the namelist and iterates through the namelist by calls to
1397 nml_write_obj. The call below has dummys in the arguments used in
1398 the treatment of derived types. */
1399
1400 void
1401 namelist_write (st_parameter_dt *dtp)
1402 {
1403 namelist_info * t1, *t2, *dummy = NULL;
1404 index_type i;
1405 index_type dummy_offset = 0;
1406 char c;
1407 char * dummy_name = NULL;
1408 unit_delim tmp_delim;
1409
1410 /* Set the delimiter for namelist output. */
1411
1412 tmp_delim = dtp->u.p.delim_status;
1413 switch (tmp_delim)
1414 {
1415 case (DELIM_QUOTE):
1416 dtp->u.p.nml_delim = '"';
1417 break;
1418
1419 case (DELIM_APOSTROPHE):
1420 dtp->u.p.nml_delim = '\'';
1421 break;
1422
1423 default:
1424 dtp->u.p.nml_delim = '\0';
1425 break;
1426 }
1427
1428 /* Temporarily disable namelist delimters. */
1429 dtp->u.p.delim_status = DELIM_NONE;
1430
1431 write_character (dtp, "&", 1, 1);
1432
1433 /* Write namelist name in upper case - f95 std. */
1434 for (i = 0 ;i < dtp->namelist_name_len ;i++ )
1435 {
1436 c = toupper (dtp->namelist_name[i]);
1437 write_character (dtp, &c, 1 ,1);
1438 }
1439
1440 if (dtp->u.p.ionml != NULL)
1441 {
1442 t1 = dtp->u.p.ionml;
1443 while (t1 != NULL)
1444 {
1445 t2 = t1;
1446 t1 = nml_write_obj (dtp, t2, dummy_offset, dummy, dummy_name);
1447 }
1448 }
1449
1450 #ifdef HAVE_CRLF
1451 write_character (dtp, " /\r\n", 1, 5);
1452 #else
1453 write_character (dtp, " /\n", 1, 4);
1454 #endif
1455
1456 /* Restore the original delimiter. */
1457 dtp->u.p.delim_status = tmp_delim;
1458 }
1459
1460 #undef NML_DIGITS