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 p = write_block (dtp, wlen - len);
312 if (p == NULL)
313 return;
314 memset (p, ' ', wlen - len);
315 }
316
317 /* Scan the source string looking for '\n' and convert it if found. */
318 qq = (gfc_char4_t *) source;
319 for (i = 0; i < wlen; i++)
320 {
321 if (qq[i] == '\n')
322 {
323 /* Write out the previously scanned characters in the string. */
324 if (bytes > 0)
325 {
326 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
327 write_utf8_char4 (dtp, q, bytes, 0);
328 else
329 write_default_char4 (dtp, q, bytes, 0);
330 bytes = 0;
331 }
332
333 /* Write out the CR_LF sequence. */
334 write_default_char4 (dtp, crlf, 2, 0);
335 }
336 else
337 bytes++;
338 }
339
340 /* Write out any remaining bytes if no LF was found. */
341 if (bytes > 0)
342 {
343 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
344 write_utf8_char4 (dtp, q, bytes, 0);
345 else
346 write_default_char4 (dtp, q, bytes, 0);
347 }
348 }
349 else
350 {
351 #endif
352 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
353 write_utf8_char4 (dtp, q, len, wlen);
354 else
355 write_default_char4 (dtp, q, len, wlen);
356 #ifdef HAVE_CRLF
357 }
358 #endif
359 }
360
361
362 static GFC_INTEGER_LARGEST
363 extract_int (const void *p, int len)
364 {
365 GFC_INTEGER_LARGEST i = 0;
366
367 if (p == NULL)
368 return i;
369
370 switch (len)
371 {
372 case 1:
373 {
374 GFC_INTEGER_1 tmp;
375 memcpy ((void *) &tmp, p, len);
376 i = tmp;
377 }
378 break;
379 case 2:
380 {
381 GFC_INTEGER_2 tmp;
382 memcpy ((void *) &tmp, p, len);
383 i = tmp;
384 }
385 break;
386 case 4:
387 {
388 GFC_INTEGER_4 tmp;
389 memcpy ((void *) &tmp, p, len);
390 i = tmp;
391 }
392 break;
393 case 8:
394 {
395 GFC_INTEGER_8 tmp;
396 memcpy ((void *) &tmp, p, len);
397 i = tmp;
398 }
399 break;
400 #ifdef HAVE_GFC_INTEGER_16
401 case 16:
402 {
403 GFC_INTEGER_16 tmp;
404 memcpy ((void *) &tmp, p, len);
405 i = tmp;
406 }
407 break;
408 #endif
409 default:
410 internal_error (NULL, "bad integer kind");
411 }
412
413 return i;
414 }
415
416 static GFC_UINTEGER_LARGEST
417 extract_uint (const void *p, int len)
418 {
419 GFC_UINTEGER_LARGEST i = 0;
420
421 if (p == NULL)
422 return i;
423
424 switch (len)
425 {
426 case 1:
427 {
428 GFC_INTEGER_1 tmp;
429 memcpy ((void *) &tmp, p, len);
430 i = (GFC_UINTEGER_1) tmp;
431 }
432 break;
433 case 2:
434 {
435 GFC_INTEGER_2 tmp;
436 memcpy ((void *) &tmp, p, len);
437 i = (GFC_UINTEGER_2) tmp;
438 }
439 break;
440 case 4:
441 {
442 GFC_INTEGER_4 tmp;
443 memcpy ((void *) &tmp, p, len);
444 i = (GFC_UINTEGER_4) tmp;
445 }
446 break;
447 case 8:
448 {
449 GFC_INTEGER_8 tmp;
450 memcpy ((void *) &tmp, p, len);
451 i = (GFC_UINTEGER_8) tmp;
452 }
453 break;
454 #ifdef HAVE_GFC_INTEGER_16
455 case 16:
456 {
457 GFC_INTEGER_16 tmp;
458 memcpy ((void *) &tmp, p, len);
459 i = (GFC_UINTEGER_16) tmp;
460 }
461 break;
462 #endif
463 default:
464 internal_error (NULL, "bad integer kind");
465 }
466
467 return i;
468 }
469
470
471 void
472 write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
473 {
474 char *p;
475 int wlen;
476 GFC_INTEGER_LARGEST n;
477
478 wlen = (f->format == FMT_G && f->u.w == 0) ? 1 : f->u.w;
479
480 p = write_block (dtp, wlen);
481 if (p == NULL)
482 return;
483
484 memset (p, ' ', wlen - 1);
485 n = extract_int (source, len);
486 p[wlen - 1] = (n) ? 'T' : 'F';
487 }
488
489
490 static void
491 write_int (st_parameter_dt *dtp, const fnode *f, const char *source, int len,
492 const char *(*conv) (GFC_UINTEGER_LARGEST, char *, size_t))
493 {
494 GFC_UINTEGER_LARGEST n = 0;
495 int w, m, digits, nzero, nblank;
496 char *p;
497 const char *q;
498 char itoa_buf[GFC_BTOA_BUF_SIZE];
499
500 w = f->u.integer.w;
501 m = f->u.integer.m;
502
503 n = extract_uint (source, len);
504
505 /* Special case: */
506
507 if (m == 0 && n == 0)
508 {
509 if (w == 0)
510 w = 1;
511
512 p = write_block (dtp, w);
513 if (p == NULL)
514 return;
515
516 memset (p, ' ', w);
517 goto done;
518 }
519
520 q = conv (n, itoa_buf, sizeof (itoa_buf));
521 digits = strlen (q);
522
523 /* Select a width if none was specified. The idea here is to always
524 print something. */
525
526 if (w == 0)
527 w = ((digits < m) ? m : digits);
528
529 p = write_block (dtp, w);
530 if (p == NULL)
531 return;
532
533 nzero = 0;
534 if (digits < m)
535 nzero = m - digits;
536
537 /* See if things will work. */
538
539 nblank = w - (nzero + digits);
540
541 if (nblank < 0)
542 {
543 star_fill (p, w);
544 goto done;
545 }
546
547
548 if (!dtp->u.p.no_leading_blank)
549 {
550 memset (p, ' ', nblank);
551 p += nblank;
552 memset (p, '0', nzero);
553 p += nzero;
554 memcpy (p, q, digits);
555 }
556 else
557 {
558 memset (p, '0', nzero);
559 p += nzero;
560 memcpy (p, q, digits);
561 p += digits;
562 memset (p, ' ', nblank);
563 dtp->u.p.no_leading_blank = 0;
564 }
565
566 done:
567 return;
568 }
569
570 static void
571 write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
572 int len,
573 const char *(*conv) (GFC_INTEGER_LARGEST, char *, size_t))
574 {
575 GFC_INTEGER_LARGEST n = 0;
576 int w, m, digits, nsign, nzero, nblank;
577 char *p;
578 const char *q;
579 sign_t sign;
580 char itoa_buf[GFC_BTOA_BUF_SIZE];
581
582 w = f->u.integer.w;
583 m = f->format == FMT_G ? -1 : f->u.integer.m;
584
585 n = extract_int (source, len);
586
587 /* Special case: */
588 if (m == 0 && n == 0)
589 {
590 if (w == 0)
591 w = 1;
592
593 p = write_block (dtp, w);
594 if (p == NULL)
595 return;
596
597 memset (p, ' ', w);
598 goto done;
599 }
600
601 sign = calculate_sign (dtp, n < 0);
602 if (n < 0)
603 n = -n;
604
605 nsign = sign == S_NONE ? 0 : 1;
606 q = conv (n, itoa_buf, sizeof (itoa_buf));
607
608 digits = strlen (q);
609
610 /* Select a width if none was specified. The idea here is to always
611 print something. */
612
613 if (w == 0)
614 w = ((digits < m) ? m : digits) + nsign;
615
616 p = write_block (dtp, w);
617 if (p == NULL)
618 return;
619
620 nzero = 0;
621 if (digits < m)
622 nzero = m - digits;
623
624 /* See if things will work. */
625
626 nblank = w - (nsign + nzero + digits);
627
628 if (nblank < 0)
629 {
630 star_fill (p, w);
631 goto done;
632 }
633
634 memset (p, ' ', nblank);
635 p += nblank;
636
637 switch (sign)
638 {
639 case S_PLUS:
640 *p++ = '+';
641 break;
642 case S_MINUS:
643 *p++ = '-';
644 break;
645 case S_NONE:
646 break;
647 }
648
649 memset (p, '0', nzero);
650 p += nzero;
651
652 memcpy (p, q, digits);
653
654 done:
655 return;
656 }
657
658
659 /* Convert unsigned octal to ascii. */
660
661 static const char *
662 otoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
663 {
664 char *p;
665
666 assert (len >= GFC_OTOA_BUF_SIZE);
667
668 if (n == 0)
669 return "0";
670
671 p = buffer + GFC_OTOA_BUF_SIZE - 1;
672 *p = '\0';
673
674 while (n != 0)
675 {
676 *--p = '0' + (n & 7);
677 n >>= 3;
678 }
679
680 return p;
681 }
682
683
684 /* Convert unsigned binary to ascii. */
685
686 static const char *
687 btoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
688 {
689 char *p;
690
691 assert (len >= GFC_BTOA_BUF_SIZE);
692
693 if (n == 0)
694 return "0";
695
696 p = buffer + GFC_BTOA_BUF_SIZE - 1;
697 *p = '\0';
698
699 while (n != 0)
700 {
701 *--p = '0' + (n & 1);
702 n >>= 1;
703 }
704
705 return p;
706 }
707
708
709 void
710 write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
711 {
712 write_decimal (dtp, f, p, len, (void *) gfc_itoa);
713 }
714
715
716 void
717 write_b (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
718 {
719 write_int (dtp, f, p, len, btoa);
720 }
721
722
723 void
724 write_o (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
725 {
726 write_int (dtp, f, p, len, otoa);
727 }
728
729 void
730 write_z (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
731 {
732 write_int (dtp, f, p, len, xtoa);
733 }
734
735
736 void
737 write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
738 {
739 write_float (dtp, f, p, len);
740 }
741
742
743 void
744 write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
745 {
746 write_float (dtp, f, p, len);
747 }
748
749
750 void
751 write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
752 {
753 write_float (dtp, f, p, len);
754 }
755
756
757 void
758 write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
759 {
760 write_float (dtp, f, p, len);
761 }
762
763
764 void
765 write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
766 {
767 write_float (dtp, f, p, len);
768 }
769
770
771 /* Take care of the X/TR descriptor. */
772
773 void
774 write_x (st_parameter_dt *dtp, int len, int nspaces)
775 {
776 char *p;
777
778 p = write_block (dtp, len);
779 if (p == NULL)
780 return;
781
782 if (nspaces > 0)
783 memset (&p[len - nspaces], ' ', nspaces);
784 }
785
786
787 /* List-directed writing. */
788
789
790 /* Write a single character to the output. Returns nonzero if
791 something goes wrong. */
792
793 static int
794 write_char (st_parameter_dt *dtp, char c)
795 {
796 char *p;
797
798 p = write_block (dtp, 1);
799 if (p == NULL)
800 return 1;
801
802 *p = c;
803
804 return 0;
805 }
806
807
808 /* Write a list-directed logical value. */
809
810 static void
811 write_logical (st_parameter_dt *dtp, const char *source, int length)
812 {
813 write_char (dtp, extract_int (source, length) ? 'T' : 'F');
814 }
815
816
817 /* Write a list-directed integer value. */
818
819 static void
820 write_integer (st_parameter_dt *dtp, const char *source, int length)
821 {
822 char *p;
823 const char *q;
824 int digits;
825 int width;
826 char itoa_buf[GFC_ITOA_BUF_SIZE];
827
828 q = gfc_itoa (extract_int (source, length), itoa_buf, sizeof (itoa_buf));
829
830 switch (length)
831 {
832 case 1:
833 width = 4;
834 break;
835
836 case 2:
837 width = 6;
838 break;
839
840 case 4:
841 width = 11;
842 break;
843
844 case 8:
845 width = 20;
846 break;
847
848 default:
849 width = 0;
850 break;
851 }
852
853 digits = strlen (q);
854
855 if (width < digits)
856 width = digits;
857 p = write_block (dtp, width);
858 if (p == NULL)
859 return;
860 if (dtp->u.p.no_leading_blank)
861 {
862 memcpy (p, q, digits);
863 memset (p + digits, ' ', width - digits);
864 }
865 else
866 {
867 memset (p, ' ', width - digits);
868 memcpy (p + width - digits, q, digits);
869 }
870 }
871
872
873 /* Write a list-directed string. We have to worry about delimiting
874 the strings if the file has been opened in that mode. */
875
876 static void
877 write_character (st_parameter_dt *dtp, const char *source, int kind, int length)
878 {
879 int i, extra;
880 char *p, d;
881
882 switch (dtp->u.p.delim_status)
883 {
884 case DELIM_APOSTROPHE:
885 d = '\'';
886 break;
887 case DELIM_QUOTE:
888 d = '"';
889 break;
890 default:
891 d = ' ';
892 break;
893 }
894
895 if (kind == 1)
896 {
897 if (d == ' ')
898 extra = 0;
899 else
900 {
901 extra = 2;
902
903 for (i = 0; i < length; i++)
904 if (source[i] == d)
905 extra++;
906 }
907
908 p = write_block (dtp, length + extra);
909 if (p == NULL)
910 return;
911
912 if (d == ' ')
913 memcpy (p, source, length);
914 else
915 {
916 *p++ = d;
917
918 for (i = 0; i < length; i++)
919 {
920 *p++ = source[i];
921 if (source[i] == d)
922 *p++ = d;
923 }
924
925 *p = d;
926 }
927 }
928 else
929 {
930 if (d == ' ')
931 {
932 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
933 write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
934 else
935 write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
936 }
937 else
938 {
939 p = write_block (dtp, 1);
940 *p = d;
941
942 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
943 write_utf8_char4 (dtp, (gfc_char4_t *) source, length, 0);
944 else
945 write_default_char4 (dtp, (gfc_char4_t *) source, length, 0);
946
947 p = write_block (dtp, 1);
948 *p = d;
949 }
950 }
951 }
952
953
954 /* Output a real number with default format.
955 This is 1PG14.7E2 for REAL(4), 1PG23.15E3 for REAL(8),
956 1PG28.19E4 for REAL(10) and 1PG43.34E4 for REAL(16). */
957
958 void
959 write_real (st_parameter_dt *dtp, const char *source, int length)
960 {
961 fnode f ;
962 int org_scale = dtp->u.p.scale_factor;
963 f.format = FMT_G;
964 dtp->u.p.scale_factor = 1;
965 switch (length)
966 {
967 case 4:
968 f.u.real.w = 15;
969 f.u.real.d = 8;
970 f.u.real.e = 2;
971 break;
972 case 8:
973 f.u.real.w = 25;
974 f.u.real.d = 17;
975 f.u.real.e = 3;
976 break;
977 case 10:
978 f.u.real.w = 29;
979 f.u.real.d = 20;
980 f.u.real.e = 4;
981 break;
982 case 16:
983 f.u.real.w = 44;
984 f.u.real.d = 35;
985 f.u.real.e = 4;
986 break;
987 default:
988 internal_error (&dtp->common, "bad real kind");
989 break;
990 }
991 write_float (dtp, &f, source , length);
992 dtp->u.p.scale_factor = org_scale;
993 }
994
995
996 static void
997 write_complex (st_parameter_dt *dtp, const char *source, int kind, size_t size)
998 {
999 char semi_comma = dtp->u.p.decimal_status == DECIMAL_POINT ? ',' : ';';
1000
1001 if (write_char (dtp, '('))
1002 return;
1003 write_real (dtp, source, kind);
1004
1005 if (write_char (dtp, semi_comma))
1006 return;
1007 write_real (dtp, source + size / 2, kind);
1008
1009 write_char (dtp, ')');
1010 }
1011
1012
1013 /* Write the separator between items. */
1014
1015 static void
1016 write_separator (st_parameter_dt *dtp)
1017 {
1018 char *p;
1019
1020 p = write_block (dtp, options.separator_len);
1021 if (p == NULL)
1022 return;
1023
1024 memcpy (p, options.separator, options.separator_len);
1025 }
1026
1027
1028 /* Write an item with list formatting.
1029 TODO: handle skipping to the next record correctly, particularly
1030 with strings. */
1031
1032 static void
1033 list_formatted_write_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
1034 size_t size)
1035 {
1036 if (dtp->u.p.current_unit == NULL)
1037 return;
1038
1039 if (dtp->u.p.first_item)
1040 {
1041 dtp->u.p.first_item = 0;
1042 write_char (dtp, ' ');
1043 }
1044 else
1045 {
1046 if (type != BT_CHARACTER || !dtp->u.p.char_flag ||
1047 dtp->u.p.delim_status != DELIM_NONE)
1048 write_separator (dtp);
1049 }
1050
1051 switch (type)
1052 {
1053 case BT_INTEGER:
1054 write_integer (dtp, p, kind);
1055 break;
1056 case BT_LOGICAL:
1057 write_logical (dtp, p, kind);
1058 break;
1059 case BT_CHARACTER:
1060 write_character (dtp, p, kind, size);
1061 break;
1062 case BT_REAL:
1063 write_real (dtp, p, kind);
1064 break;
1065 case BT_COMPLEX:
1066 write_complex (dtp, p, kind, size);
1067 break;
1068 default:
1069 internal_error (&dtp->common, "list_formatted_write(): Bad type");
1070 }
1071
1072 dtp->u.p.char_flag = (type == BT_CHARACTER);
1073 }
1074
1075
1076 void
1077 list_formatted_write (st_parameter_dt *dtp, bt type, void *p, int kind,
1078 size_t size, size_t nelems)
1079 {
1080 size_t elem;
1081 char *tmp;
1082 size_t stride = type == BT_CHARACTER ?
1083 size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
1084
1085 tmp = (char *) p;
1086
1087 /* Big loop over all the elements. */
1088 for (elem = 0; elem < nelems; elem++)
1089 {
1090 dtp->u.p.item_count++;
1091 list_formatted_write_scalar (dtp, type, tmp + elem * stride, kind, size);
1092 }
1093 }
1094
1095 /* NAMELIST OUTPUT
1096
1097 nml_write_obj writes a namelist object to the output stream. It is called
1098 recursively for derived type components:
1099 obj = is the namelist_info for the current object.
1100 offset = the offset relative to the address held by the object for
1101 derived type arrays.
1102 base = is the namelist_info of the derived type, when obj is a
1103 component.
1104 base_name = the full name for a derived type, including qualifiers
1105 if any.
1106 The returned value is a pointer to the object beyond the last one
1107 accessed, including nested derived types. Notice that the namelist is
1108 a linear linked list of objects, including derived types and their
1109 components. A tree, of sorts, is implied by the compound names of
1110 the derived type components and this is how this function recurses through
1111 the list. */
1112
1113 /* A generous estimate of the number of characters needed to print
1114 repeat counts and indices, including commas, asterices and brackets. */
1115
1116 #define NML_DIGITS 20
1117
1118 static namelist_info *
1119 nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
1120 namelist_info * base, char * base_name)
1121 {
1122 int rep_ctr;
1123 int num;
1124 int nml_carry;
1125 index_type len;
1126 index_type obj_size;
1127 index_type nelem;
1128 index_type dim_i;
1129 index_type clen;
1130 index_type elem_ctr;
1131 index_type obj_name_len;
1132 void * p ;
1133 char cup;
1134 char * obj_name;
1135 char * ext_name;
1136 char rep_buff[NML_DIGITS];
1137 namelist_info * cmp;
1138 namelist_info * retval = obj->next;
1139 size_t base_name_len;
1140 size_t base_var_name_len;
1141 size_t tot_len;
1142 unit_delim tmp_delim;
1143
1144 /* Set the character to be used to separate values
1145 to a comma or semi-colon. */
1146
1147 char semi_comma = dtp->u.p.decimal_status == DECIMAL_POINT ? ',' : ';';
1148
1149 /* Write namelist variable names in upper case. If a derived type,
1150 nothing is output. If a component, base and base_name are set. */
1151
1152 if (obj->type != GFC_DTYPE_DERIVED)
1153 {
1154 #ifdef HAVE_CRLF
1155 write_character (dtp, "\r\n ", 1, 3);
1156 #else
1157 write_character (dtp, "\n ", 1, 2);
1158 #endif
1159 len = 0;
1160 if (base)
1161 {
1162 len =strlen (base->var_name);
1163 for (dim_i = 0; dim_i < (index_type) strlen (base_name); dim_i++)
1164 {
1165 cup = toupper (base_name[dim_i]);
1166 write_character (dtp, &cup, 1, 1);
1167 }
1168 }
1169 for (dim_i =len; dim_i < (index_type) strlen (obj->var_name); dim_i++)
1170 {
1171 cup = toupper (obj->var_name[dim_i]);
1172 write_character (dtp, &cup, 1, 1);
1173 }
1174 write_character (dtp, "=", 1, 1);
1175 }
1176
1177 /* Counts the number of data output on a line, including names. */
1178
1179 num = 1;
1180
1181 len = obj->len;
1182
1183 switch (obj->type)
1184 {
1185
1186 case GFC_DTYPE_REAL:
1187 obj_size = size_from_real_kind (len);
1188 break;
1189
1190 case GFC_DTYPE_COMPLEX:
1191 obj_size = size_from_complex_kind (len);
1192 break;
1193
1194 case GFC_DTYPE_CHARACTER:
1195 obj_size = obj->string_length;
1196 break;
1197
1198 default:
1199 obj_size = len;
1200 }
1201
1202 if (obj->var_rank)
1203 obj_size = obj->size;
1204
1205 /* Set the index vector and count the number of elements. */
1206
1207 nelem = 1;
1208 for (dim_i=0; dim_i < obj->var_rank; dim_i++)
1209 {
1210 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1211 nelem = nelem * (obj->dim[dim_i].ubound + 1 - obj->dim[dim_i].lbound);
1212 }
1213
1214 /* Main loop to output the data held in the object. */
1215
1216 rep_ctr = 1;
1217 for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
1218 {
1219
1220 /* Build the pointer to the data value. The offset is passed by
1221 recursive calls to this function for arrays of derived types.
1222 Is NULL otherwise. */
1223
1224 p = (void *)(obj->mem_pos + elem_ctr * obj_size);
1225 p += offset;
1226
1227 /* Check for repeat counts of intrinsic types. */
1228
1229 if ((elem_ctr < (nelem - 1)) &&
1230 (obj->type != GFC_DTYPE_DERIVED) &&
1231 !memcmp (p, (void*)(p + obj_size ), obj_size ))
1232 {
1233 rep_ctr++;
1234 }
1235
1236 /* Execute a repeated output. Note the flag no_leading_blank that
1237 is used in the functions used to output the intrinsic types. */
1238
1239 else
1240 {
1241 if (rep_ctr > 1)
1242 {
1243 sprintf(rep_buff, " %d*", rep_ctr);
1244 write_character (dtp, rep_buff, 1, strlen (rep_buff));
1245 dtp->u.p.no_leading_blank = 1;
1246 }
1247 num++;
1248
1249 /* Output the data, if an intrinsic type, or recurse into this
1250 routine to treat derived types. */
1251
1252 switch (obj->type)
1253 {
1254
1255 case GFC_DTYPE_INTEGER:
1256 write_integer (dtp, p, len);
1257 break;
1258
1259 case GFC_DTYPE_LOGICAL:
1260 write_logical (dtp, p, len);
1261 break;
1262
1263 case GFC_DTYPE_CHARACTER:
1264 tmp_delim = dtp->u.p.delim_status;
1265 if (dtp->u.p.nml_delim == '"')
1266 dtp->u.p.delim_status = DELIM_QUOTE;
1267 if (dtp->u.p.nml_delim == '\'')
1268 dtp->u.p.delim_status = DELIM_APOSTROPHE;
1269 write_character (dtp, p, 1, obj->string_length);
1270 dtp->u.p.delim_status = tmp_delim;
1271 break;
1272
1273 case GFC_DTYPE_REAL:
1274 write_real (dtp, p, len);
1275 break;
1276
1277 case GFC_DTYPE_COMPLEX:
1278 dtp->u.p.no_leading_blank = 0;
1279 num++;
1280 write_complex (dtp, p, len, obj_size);
1281 break;
1282
1283 case GFC_DTYPE_DERIVED:
1284
1285 /* To treat a derived type, we need to build two strings:
1286 ext_name = the name, including qualifiers that prepends
1287 component names in the output - passed to
1288 nml_write_obj.
1289 obj_name = the derived type name with no qualifiers but %
1290 appended. This is used to identify the
1291 components. */
1292
1293 /* First ext_name => get length of all possible components */
1294
1295 base_name_len = base_name ? strlen (base_name) : 0;
1296 base_var_name_len = base ? strlen (base->var_name) : 0;
1297 ext_name = (char*)get_mem ( base_name_len
1298 + base_var_name_len
1299 + strlen (obj->var_name)
1300 + obj->var_rank * NML_DIGITS
1301 + 1);
1302
1303 memcpy (ext_name, base_name, base_name_len);
1304 clen = strlen (obj->var_name + base_var_name_len);
1305 memcpy (ext_name + base_name_len,
1306 obj->var_name + base_var_name_len, clen);
1307
1308 /* Append the qualifier. */
1309
1310 tot_len = base_name_len + clen;
1311 for (dim_i = 0; dim_i < obj->var_rank; dim_i++)
1312 {
1313 if (!dim_i)
1314 {
1315 ext_name[tot_len] = '(';
1316 tot_len++;
1317 }
1318 sprintf (ext_name + tot_len, "%d", (int) obj->ls[dim_i].idx);
1319 tot_len += strlen (ext_name + tot_len);
1320 ext_name[tot_len] = (dim_i == obj->var_rank - 1) ? ')' : ',';
1321 tot_len++;
1322 }
1323
1324 ext_name[tot_len] = '\0';
1325
1326 /* Now obj_name. */
1327
1328 obj_name_len = strlen (obj->var_name) + 1;
1329 obj_name = get_mem (obj_name_len+1);
1330 memcpy (obj_name, obj->var_name, obj_name_len-1);
1331 memcpy (obj_name + obj_name_len-1, "%", 2);
1332
1333 /* Now loop over the components. Update the component pointer
1334 with the return value from nml_write_obj => this loop jumps
1335 past nested derived types. */
1336
1337 for (cmp = obj->next;
1338 cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
1339 cmp = retval)
1340 {
1341 retval = nml_write_obj (dtp, cmp,
1342 (index_type)(p - obj->mem_pos),
1343 obj, ext_name);
1344 }
1345
1346 free_mem (obj_name);
1347 free_mem (ext_name);
1348 goto obj_loop;
1349
1350 default:
1351 internal_error (&dtp->common, "Bad type for namelist write");
1352 }
1353
1354 /* Reset the leading blank suppression, write a comma (or semi-colon)
1355 and, if 5 values have been output, write a newline and advance
1356 to column 2. Reset the repeat counter. */
1357
1358 dtp->u.p.no_leading_blank = 0;
1359 write_character (dtp, &semi_comma, 1, 1);
1360 if (num > 5)
1361 {
1362 num = 0;
1363 #ifdef HAVE_CRLF
1364 write_character (dtp, "\r\n ", 1, 3);
1365 #else
1366 write_character (dtp, "\n ", 1, 2);
1367 #endif
1368 }
1369 rep_ctr = 1;
1370 }
1371
1372 /* Cycle through and increment the index vector. */
1373
1374 obj_loop:
1375
1376 nml_carry = 1;
1377 for (dim_i = 0; nml_carry && (dim_i < obj->var_rank); dim_i++)
1378 {
1379 obj->ls[dim_i].idx += nml_carry ;
1380 nml_carry = 0;
1381 if (obj->ls[dim_i].idx > (ssize_t)obj->dim[dim_i].ubound)
1382 {
1383 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1384 nml_carry = 1;
1385 }
1386 }
1387 }
1388
1389 /* Return a pointer beyond the furthest object accessed. */
1390
1391 return retval;
1392 }
1393
1394 /* This is the entry function for namelist writes. It outputs the name
1395 of the namelist and iterates through the namelist by calls to
1396 nml_write_obj. The call below has dummys in the arguments used in
1397 the treatment of derived types. */
1398
1399 void
1400 namelist_write (st_parameter_dt *dtp)
1401 {
1402 namelist_info * t1, *t2, *dummy = NULL;
1403 index_type i;
1404 index_type dummy_offset = 0;
1405 char c;
1406 char * dummy_name = NULL;
1407 unit_delim tmp_delim;
1408
1409 /* Set the delimiter for namelist output. */
1410
1411 tmp_delim = dtp->u.p.delim_status;
1412 switch (tmp_delim)
1413 {
1414 case (DELIM_QUOTE):
1415 dtp->u.p.nml_delim = '"';
1416 break;
1417
1418 case (DELIM_APOSTROPHE):
1419 dtp->u.p.nml_delim = '\'';
1420 break;
1421
1422 default:
1423 dtp->u.p.nml_delim = '\0';
1424 break;
1425 }
1426
1427 /* Temporarily disable namelist delimters. */
1428 dtp->u.p.delim_status = DELIM_NONE;
1429
1430 write_character (dtp, "&", 1, 1);
1431
1432 /* Write namelist name in upper case - f95 std. */
1433 for (i = 0 ;i < dtp->namelist_name_len ;i++ )
1434 {
1435 c = toupper (dtp->namelist_name[i]);
1436 write_character (dtp, &c, 1 ,1);
1437 }
1438
1439 if (dtp->u.p.ionml != NULL)
1440 {
1441 t1 = dtp->u.p.ionml;
1442 while (t1 != NULL)
1443 {
1444 t2 = t1;
1445 t1 = nml_write_obj (dtp, t2, dummy_offset, dummy, dummy_name);
1446 }
1447 }
1448
1449 #ifdef HAVE_CRLF
1450 write_character (dtp, " /\r\n", 1, 5);
1451 #else
1452 write_character (dtp, " /\n", 1, 4);
1453 #endif
1454
1455 /* Restore the original delimiter. */
1456 dtp->u.p.delim_status = tmp_delim;
1457 }
1458
1459 #undef NML_DIGITS