Daily bump.
[official-gcc.git] / libgfortran / io / write.c
blob9ff48049dac1fad27210f0b69e144fa13c1c2018
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
3 Namelist output contributed by Paul Thomas
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
19 executable.)
21 Libgfortran is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with Libgfortran; see the file COPYING. If not, write to
28 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
29 Boston, MA 02110-1301, USA. */
31 #include "config.h"
32 #include <assert.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <float.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include "libgfortran.h"
39 #include "io.h"
41 #define star_fill(p, n) memset(p, '*', n)
44 typedef enum
45 { SIGN_NONE, SIGN_MINUS, SIGN_PLUS }
46 sign_t;
49 void
50 write_a (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
52 int wlen;
53 char *p;
55 wlen = f->u.string.length < 0 ? len : f->u.string.length;
57 #ifdef HAVE_CRLF
58 /* If this is formatted STREAM IO convert any embedded line feed characters
59 to CR_LF on systems that use that sequence for newlines. See F2003
60 Standard sections 10.6.3 and 9.9 for further information. */
61 if (is_stream_io (dtp))
63 const char crlf[] = "\r\n";
64 int i, q, bytes;
65 q = bytes = 0;
67 /* Write out any padding if needed. */
68 if (len < wlen)
70 p = write_block (dtp, wlen - len);
71 if (p == NULL)
72 return;
73 memset (p, ' ', wlen - len);
76 /* Scan the source string looking for '\n' and convert it if found. */
77 for (i = 0; i < wlen; i++)
79 if (source[i] == '\n')
81 /* Write out the previously scanned characters in the string. */
82 if (bytes > 0)
84 p = write_block (dtp, bytes);
85 if (p == NULL)
86 return;
87 memcpy (p, &source[q], bytes);
88 q += bytes;
89 bytes = 0;
92 /* Write out the CR_LF sequence. */
93 q++;
94 p = write_block (dtp, 2);
95 if (p == NULL)
96 return;
97 memcpy (p, crlf, 2);
99 else
100 bytes++;
103 /* Write out any remaining bytes if no LF was found. */
104 if (bytes > 0)
106 p = write_block (dtp, bytes);
107 if (p == NULL)
108 return;
109 memcpy (p, &source[q], bytes);
112 else
114 #endif
115 p = write_block (dtp, wlen);
116 if (p == NULL)
117 return;
119 if (wlen < len)
120 memcpy (p, source, wlen);
121 else
123 memset (p, ' ', wlen - len);
124 memcpy (p + wlen - len, source, len);
126 #ifdef HAVE_CRLF
128 #endif
131 static GFC_INTEGER_LARGEST
132 extract_int (const void *p, int len)
134 GFC_INTEGER_LARGEST i = 0;
136 if (p == NULL)
137 return i;
139 switch (len)
141 case 1:
143 GFC_INTEGER_1 tmp;
144 memcpy ((void *) &tmp, p, len);
145 i = tmp;
147 break;
148 case 2:
150 GFC_INTEGER_2 tmp;
151 memcpy ((void *) &tmp, p, len);
152 i = tmp;
154 break;
155 case 4:
157 GFC_INTEGER_4 tmp;
158 memcpy ((void *) &tmp, p, len);
159 i = tmp;
161 break;
162 case 8:
164 GFC_INTEGER_8 tmp;
165 memcpy ((void *) &tmp, p, len);
166 i = tmp;
168 break;
169 #ifdef HAVE_GFC_INTEGER_16
170 case 16:
172 GFC_INTEGER_16 tmp;
173 memcpy ((void *) &tmp, p, len);
174 i = tmp;
176 break;
177 #endif
178 default:
179 internal_error (NULL, "bad integer kind");
182 return i;
185 static GFC_UINTEGER_LARGEST
186 extract_uint (const void *p, int len)
188 GFC_UINTEGER_LARGEST i = 0;
190 if (p == NULL)
191 return i;
193 switch (len)
195 case 1:
197 GFC_INTEGER_1 tmp;
198 memcpy ((void *) &tmp, p, len);
199 i = (GFC_UINTEGER_1) tmp;
201 break;
202 case 2:
204 GFC_INTEGER_2 tmp;
205 memcpy ((void *) &tmp, p, len);
206 i = (GFC_UINTEGER_2) tmp;
208 break;
209 case 4:
211 GFC_INTEGER_4 tmp;
212 memcpy ((void *) &tmp, p, len);
213 i = (GFC_UINTEGER_4) tmp;
215 break;
216 case 8:
218 GFC_INTEGER_8 tmp;
219 memcpy ((void *) &tmp, p, len);
220 i = (GFC_UINTEGER_8) tmp;
222 break;
223 #ifdef HAVE_GFC_INTEGER_16
224 case 16:
226 GFC_INTEGER_16 tmp;
227 memcpy ((void *) &tmp, p, len);
228 i = (GFC_UINTEGER_16) tmp;
230 break;
231 #endif
232 default:
233 internal_error (NULL, "bad integer kind");
236 return i;
239 static GFC_REAL_LARGEST
240 extract_real (const void *p, int len)
242 GFC_REAL_LARGEST i = 0;
243 switch (len)
245 case 4:
247 GFC_REAL_4 tmp;
248 memcpy ((void *) &tmp, p, len);
249 i = tmp;
251 break;
252 case 8:
254 GFC_REAL_8 tmp;
255 memcpy ((void *) &tmp, p, len);
256 i = tmp;
258 break;
259 #ifdef HAVE_GFC_REAL_10
260 case 10:
262 GFC_REAL_10 tmp;
263 memcpy ((void *) &tmp, p, len);
264 i = tmp;
266 break;
267 #endif
268 #ifdef HAVE_GFC_REAL_16
269 case 16:
271 GFC_REAL_16 tmp;
272 memcpy ((void *) &tmp, p, len);
273 i = tmp;
275 break;
276 #endif
277 default:
278 internal_error (NULL, "bad real kind");
280 return i;
284 /* Given a flag that indicate if a value is negative or not, return a
285 sign_t that gives the sign that we need to produce. */
287 static sign_t
288 calculate_sign (st_parameter_dt *dtp, int negative_flag)
290 sign_t s = SIGN_NONE;
292 if (negative_flag)
293 s = SIGN_MINUS;
294 else
295 switch (dtp->u.p.sign_status)
297 case SIGN_SP:
298 s = SIGN_PLUS;
299 break;
300 case SIGN_SS:
301 s = SIGN_NONE;
302 break;
303 case SIGN_S:
304 s = options.optional_plus ? SIGN_PLUS : SIGN_NONE;
305 break;
308 return s;
312 /* Returns the value of 10**d. */
314 static GFC_REAL_LARGEST
315 calculate_exp (int d)
317 int i;
318 GFC_REAL_LARGEST r = 1.0;
320 for (i = 0; i< (d >= 0 ? d : -d); i++)
321 r *= 10;
323 r = (d >= 0) ? r : 1.0 / r;
325 return r;
329 /* Generate corresponding I/O format for FMT_G output.
330 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
331 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
333 Data Magnitude Equivalent Conversion
334 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
335 m = 0 F(w-n).(d-1), n' '
336 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
337 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
338 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
339 ................ ..........
340 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
341 m >= 10**d-0.5 Ew.d[Ee]
343 notes: for Gw.d , n' ' means 4 blanks
344 for Gw.dEe, n' ' means e+2 blanks */
346 static fnode *
347 calculate_G_format (st_parameter_dt *dtp, const fnode *f,
348 GFC_REAL_LARGEST value, int *num_blank)
350 int e = f->u.real.e;
351 int d = f->u.real.d;
352 int w = f->u.real.w;
353 fnode *newf;
354 GFC_REAL_LARGEST m, exp_d;
355 int low, high, mid;
356 int ubound, lbound;
358 newf = get_mem (sizeof (fnode));
360 /* Absolute value. */
361 m = (value > 0.0) ? value : -value;
363 /* In case of the two data magnitude ranges,
364 generate E editing, Ew.d[Ee]. */
365 exp_d = calculate_exp (d);
366 if ((m > 0.0 && m < 0.1 - 0.05 / exp_d) || (m >= exp_d - 0.5 ) ||
367 ((m == 0.0) && !(compile_options.allow_std & GFC_STD_F2003)))
369 newf->format = FMT_E;
370 newf->u.real.w = w;
371 newf->u.real.d = d;
372 newf->u.real.e = e;
373 *num_blank = 0;
374 return newf;
377 /* Use binary search to find the data magnitude range. */
378 mid = 0;
379 low = 0;
380 high = d + 1;
381 lbound = 0;
382 ubound = d + 1;
384 while (low <= high)
386 GFC_REAL_LARGEST temp;
387 mid = (low + high) / 2;
389 /* 0.1 * 10**mid - 0.5 * 10**(mid-d-1) */
390 temp = 0.1 * calculate_exp (mid) - 0.5 * calculate_exp (mid - d - 1);
392 if (m < temp)
394 ubound = mid;
395 if (ubound == lbound + 1)
396 break;
397 high = mid - 1;
399 else if (m > temp)
401 lbound = mid;
402 if (ubound == lbound + 1)
404 mid ++;
405 break;
407 low = mid + 1;
409 else
410 break;
413 /* Pad with blanks where the exponent would be. */
414 if (e < 0)
415 *num_blank = 4;
416 else
417 *num_blank = e + 2;
419 /* Generate the F editing. F(w-n).(-(mid-d-1)), n' '. */
420 newf->format = FMT_F;
421 newf->u.real.w = f->u.real.w - *num_blank;
423 /* Special case. */
424 if (m == 0.0)
425 newf->u.real.d = d - 1;
426 else
427 newf->u.real.d = - (mid - d - 1);
429 /* For F editing, the scale factor is ignored. */
430 dtp->u.p.scale_factor = 0;
431 return newf;
435 /* Output a real number according to its format which is FMT_G free. */
437 static void
438 output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
440 #if defined(HAVE_GFC_REAL_16) && __LDBL_DIG__ > 18
441 # define MIN_FIELD_WIDTH 46
442 #else
443 # define MIN_FIELD_WIDTH 31
444 #endif
445 #define STR(x) STR1(x)
446 #define STR1(x) #x
447 /* This must be large enough to accurately hold any value. */
448 char buffer[MIN_FIELD_WIDTH+1];
449 char *out;
450 char *digits;
451 int e;
452 char expchar;
453 format_token ft;
454 int w;
455 int d;
456 int edigits;
457 int ndigits;
458 /* Number of digits before the decimal point. */
459 int nbefore;
460 /* Number of zeros after the decimal point. */
461 int nzero;
462 /* Number of digits after the decimal point. */
463 int nafter;
464 /* Number of zeros after the decimal point, whatever the precision. */
465 int nzero_real;
466 int leadzero;
467 int nblanks;
468 int i;
469 sign_t sign;
470 double abslog;
472 ft = f->format;
473 w = f->u.real.w;
474 d = f->u.real.d;
476 nzero_real = -1;
479 /* We should always know the field width and precision. */
480 if (d < 0)
481 internal_error (&dtp->common, "Unspecified precision");
483 /* Use sprintf to print the number in the format +D.DDDDe+ddd
484 For an N digit exponent, this gives us (MIN_FIELD_WIDTH-5)-N digits
485 after the decimal point, plus another one before the decimal point. */
486 sign = calculate_sign (dtp, value < 0.0);
487 if (value < 0)
488 value = -value;
490 /* Special case when format specifies no digits after the decimal point. */
491 if (d == 0)
493 if (value < 0.5)
494 value = 0.0;
495 else if (value < 1.0)
496 value = value + 0.5;
499 /* Printf always prints at least two exponent digits. */
500 if (value == 0)
501 edigits = 2;
502 else
504 #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
505 abslog = fabs((double) log10l(value));
506 #else
507 abslog = fabs(log10(value));
508 #endif
509 if (abslog < 100)
510 edigits = 2;
511 else
512 edigits = 1 + (int) log10(abslog);
515 if (ft == FMT_F || ft == FMT_EN
516 || ((ft == FMT_D || ft == FMT_E) && dtp->u.p.scale_factor != 0))
518 /* Always convert at full precision to avoid double rounding. */
519 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
521 else
523 /* We know the number of digits, so can let printf do the rounding
524 for us. */
525 if (ft == FMT_ES)
526 ndigits = d + 1;
527 else
528 ndigits = d;
529 if (ndigits > MIN_FIELD_WIDTH - 4 - edigits)
530 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
533 /* # The result will always contain a decimal point, even if no
534 * digits follow it
536 * - The converted value is to be left adjusted on the field boundary
538 * + A sign (+ or -) always be placed before a number
540 * MIN_FIELD_WIDTH minimum field width
542 * * (ndigits-1) is used as the precision
544 * e format: [-]d.ddde±dd where there is one digit before the
545 * decimal-point character and the number of digits after it is
546 * equal to the precision. The exponent always contains at least two
547 * digits; if the value is zero, the exponent is 00.
549 sprintf (buffer, "%+-#" STR(MIN_FIELD_WIDTH) ".*"
550 GFC_REAL_LARGEST_FORMAT "e", ndigits - 1, value);
552 /* Check the resulting string has punctuation in the correct places. */
553 if (d != 0 && (buffer[2] != '.' || buffer[ndigits + 2] != 'e'))
554 internal_error (&dtp->common, "printf is broken");
556 /* Read the exponent back in. */
557 e = atoi (&buffer[ndigits + 3]) + 1;
559 /* Make sure zero comes out as 0.0e0. */
560 if (value == 0.0)
561 e = 0;
563 /* Normalize the fractional component. */
564 buffer[2] = buffer[1];
565 digits = &buffer[2];
567 /* Figure out where to place the decimal point. */
568 switch (ft)
570 case FMT_F:
571 nbefore = e + dtp->u.p.scale_factor;
572 if (nbefore < 0)
574 nzero = -nbefore;
575 nzero_real = nzero;
576 if (nzero > d)
577 nzero = d;
578 nafter = d - nzero;
579 nbefore = 0;
581 else
583 nzero = 0;
584 nafter = d;
586 expchar = 0;
587 break;
589 case FMT_E:
590 case FMT_D:
591 i = dtp->u.p.scale_factor;
592 if (value != 0.0)
593 e -= i;
594 if (i < 0)
596 nbefore = 0;
597 nzero = -i;
598 nafter = d + i;
600 else if (i > 0)
602 nbefore = i;
603 nzero = 0;
604 nafter = (d - i) + 1;
606 else /* i == 0 */
608 nbefore = 0;
609 nzero = 0;
610 nafter = d;
613 if (ft == FMT_E)
614 expchar = 'E';
615 else
616 expchar = 'D';
617 break;
619 case FMT_EN:
620 /* The exponent must be a multiple of three, with 1-3 digits before
621 the decimal point. */
622 if (value != 0.0)
623 e--;
624 if (e >= 0)
625 nbefore = e % 3;
626 else
628 nbefore = (-e) % 3;
629 if (nbefore != 0)
630 nbefore = 3 - nbefore;
632 e -= nbefore;
633 nbefore++;
634 nzero = 0;
635 nafter = d;
636 expchar = 'E';
637 break;
639 case FMT_ES:
640 if (value != 0.0)
641 e--;
642 nbefore = 1;
643 nzero = 0;
644 nafter = d;
645 expchar = 'E';
646 break;
648 default:
649 /* Should never happen. */
650 internal_error (&dtp->common, "Unexpected format token");
653 /* Round the value. */
654 if (nbefore + nafter == 0)
656 ndigits = 0;
657 if (nzero_real == d && digits[0] >= '5')
659 /* We rounded to zero but shouldn't have */
660 nzero--;
661 nafter = 1;
662 digits[0] = '1';
663 ndigits = 1;
666 else if (nbefore + nafter < ndigits)
668 ndigits = nbefore + nafter;
669 i = ndigits;
670 if (digits[i] >= '5')
672 /* Propagate the carry. */
673 for (i--; i >= 0; i--)
675 if (digits[i] != '9')
677 digits[i]++;
678 break;
680 digits[i] = '0';
683 if (i < 0)
685 /* The carry overflowed. Fortunately we have some spare space
686 at the start of the buffer. We may discard some digits, but
687 this is ok because we already know they are zero. */
688 digits--;
689 digits[0] = '1';
690 if (ft == FMT_F)
692 if (nzero > 0)
694 nzero--;
695 nafter++;
697 else
698 nbefore++;
700 else if (ft == FMT_EN)
702 nbefore++;
703 if (nbefore == 4)
705 nbefore = 1;
706 e += 3;
709 else
710 e++;
715 /* Calculate the format of the exponent field. */
716 if (expchar)
718 edigits = 1;
719 for (i = abs (e); i >= 10; i /= 10)
720 edigits++;
722 if (f->u.real.e < 0)
724 /* Width not specified. Must be no more than 3 digits. */
725 if (e > 999 || e < -999)
726 edigits = -1;
727 else
729 edigits = 4;
730 if (e > 99 || e < -99)
731 expchar = ' ';
734 else
736 /* Exponent width specified, check it is wide enough. */
737 if (edigits > f->u.real.e)
738 edigits = -1;
739 else
740 edigits = f->u.real.e + 2;
743 else
744 edigits = 0;
746 /* Pick a field size if none was specified. */
747 if (w <= 0)
748 w = nbefore + nzero + nafter + (sign != SIGN_NONE ? 2 : 1);
750 /* Create the ouput buffer. */
751 out = write_block (dtp, w);
752 if (out == NULL)
753 return;
755 /* Zero values always output as positive, even if the value was negative
756 before rounding. */
757 for (i = 0; i < ndigits; i++)
759 if (digits[i] != '0')
760 break;
762 if (i == ndigits)
763 sign = calculate_sign (dtp, 0);
765 /* Work out how much padding is needed. */
766 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
767 if (sign != SIGN_NONE)
768 nblanks--;
770 /* Check the value fits in the specified field width. */
771 if (nblanks < 0 || edigits == -1)
773 star_fill (out, w);
774 return;
777 /* See if we have space for a zero before the decimal point. */
778 if (nbefore == 0 && nblanks > 0)
780 leadzero = 1;
781 nblanks--;
783 else
784 leadzero = 0;
786 /* Pad to full field width. */
789 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
791 memset (out, ' ', nblanks);
792 out += nblanks;
795 /* Output the initial sign (if any). */
796 if (sign == SIGN_PLUS)
797 *(out++) = '+';
798 else if (sign == SIGN_MINUS)
799 *(out++) = '-';
801 /* Output an optional leading zero. */
802 if (leadzero)
803 *(out++) = '0';
805 /* Output the part before the decimal point, padding with zeros. */
806 if (nbefore > 0)
808 if (nbefore > ndigits)
809 i = ndigits;
810 else
811 i = nbefore;
813 memcpy (out, digits, i);
814 while (i < nbefore)
815 out[i++] = '0';
817 digits += i;
818 ndigits -= i;
819 out += nbefore;
821 /* Output the decimal point. */
822 *(out++) = '.';
824 /* Output leading zeros after the decimal point. */
825 if (nzero > 0)
827 for (i = 0; i < nzero; i++)
828 *(out++) = '0';
831 /* Output digits after the decimal point, padding with zeros. */
832 if (nafter > 0)
834 if (nafter > ndigits)
835 i = ndigits;
836 else
837 i = nafter;
839 memcpy (out, digits, i);
840 while (i < nafter)
841 out[i++] = '0';
843 digits += i;
844 ndigits -= i;
845 out += nafter;
848 /* Output the exponent. */
849 if (expchar)
851 if (expchar != ' ')
853 *(out++) = expchar;
854 edigits--;
856 #if HAVE_SNPRINTF
857 snprintf (buffer, sizeof (buffer), "%+0*d", edigits, e);
858 #else
859 sprintf (buffer, "%+0*d", edigits, e);
860 #endif
861 memcpy (out, buffer, edigits);
864 if (dtp->u.p.no_leading_blank)
866 out += edigits;
867 memset( out , ' ' , nblanks );
868 dtp->u.p.no_leading_blank = 0;
870 #undef STR
871 #undef STR1
872 #undef MIN_FIELD_WIDTH
876 void
877 write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
879 char *p;
880 GFC_INTEGER_LARGEST n;
882 p = write_block (dtp, f->u.w);
883 if (p == NULL)
884 return;
886 memset (p, ' ', f->u.w - 1);
887 n = extract_int (source, len);
888 p[f->u.w - 1] = (n) ? 'T' : 'F';
891 /* Output a real number according to its format. */
893 static void
894 write_float (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
896 GFC_REAL_LARGEST n;
897 int nb =0, res, save_scale_factor;
898 char * p, fin;
899 fnode *f2 = NULL;
901 n = extract_real (source, len);
903 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
905 res = isfinite (n);
906 if (res == 0)
908 nb = f->u.real.w;
910 /* If the field width is zero, the processor must select a width
911 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
913 if (nb == 0) nb = 4;
914 p = write_block (dtp, nb);
915 if (p == NULL)
916 return;
917 if (nb < 3)
919 memset (p, '*',nb);
920 return;
923 memset(p, ' ', nb);
924 res = !isnan (n);
925 if (res != 0)
927 if (signbit(n))
930 /* If the sign is negative and the width is 3, there is
931 insufficient room to output '-Inf', so output asterisks */
933 if (nb == 3)
935 memset (p, '*',nb);
936 return;
939 /* The negative sign is mandatory */
941 fin = '-';
943 else
945 /* The positive sign is optional, but we output it for
946 consistency */
948 fin = '+';
950 if (nb > 8)
952 /* We have room, so output 'Infinity' */
954 memcpy(p + nb - 8, "Infinity", 8);
955 else
957 /* For the case of width equals 8, there is not enough room
958 for the sign and 'Infinity' so we go with 'Inf' */
960 memcpy(p + nb - 3, "Inf", 3);
961 if (nb < 9 && nb > 3)
962 p[nb - 4] = fin; /* Put the sign in front of Inf */
963 else if (nb > 8)
964 p[nb - 9] = fin; /* Put the sign in front of Infinity */
966 else
967 memcpy(p + nb - 3, "NaN", 3);
968 return;
972 if (f->format != FMT_G)
973 output_float (dtp, f, n);
974 else
976 save_scale_factor = dtp->u.p.scale_factor;
977 f2 = calculate_G_format (dtp, f, n, &nb);
978 output_float (dtp, f2, n);
979 dtp->u.p.scale_factor = save_scale_factor;
980 if (f2 != NULL)
981 free_mem(f2);
983 if (nb > 0)
985 p = write_block (dtp, nb);
986 if (p == NULL)
987 return;
988 memset (p, ' ', nb);
994 static void
995 write_int (st_parameter_dt *dtp, const fnode *f, const char *source, int len,
996 const char *(*conv) (GFC_UINTEGER_LARGEST, char *, size_t))
998 GFC_UINTEGER_LARGEST n = 0;
999 int w, m, digits, nzero, nblank;
1000 char *p;
1001 const char *q;
1002 char itoa_buf[GFC_BTOA_BUF_SIZE];
1004 w = f->u.integer.w;
1005 m = f->u.integer.m;
1007 n = extract_uint (source, len);
1009 /* Special case: */
1011 if (m == 0 && n == 0)
1013 if (w == 0)
1014 w = 1;
1016 p = write_block (dtp, w);
1017 if (p == NULL)
1018 return;
1020 memset (p, ' ', w);
1021 goto done;
1024 q = conv (n, itoa_buf, sizeof (itoa_buf));
1025 digits = strlen (q);
1027 /* Select a width if none was specified. The idea here is to always
1028 print something. */
1030 if (w == 0)
1031 w = ((digits < m) ? m : digits);
1033 p = write_block (dtp, w);
1034 if (p == NULL)
1035 return;
1037 nzero = 0;
1038 if (digits < m)
1039 nzero = m - digits;
1041 /* See if things will work. */
1043 nblank = w - (nzero + digits);
1045 if (nblank < 0)
1047 star_fill (p, w);
1048 goto done;
1052 if (!dtp->u.p.no_leading_blank)
1054 memset (p, ' ', nblank);
1055 p += nblank;
1056 memset (p, '0', nzero);
1057 p += nzero;
1058 memcpy (p, q, digits);
1060 else
1062 memset (p, '0', nzero);
1063 p += nzero;
1064 memcpy (p, q, digits);
1065 p += digits;
1066 memset (p, ' ', nblank);
1067 dtp->u.p.no_leading_blank = 0;
1070 done:
1071 return;
1074 static void
1075 write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
1076 int len,
1077 const char *(*conv) (GFC_INTEGER_LARGEST, char *, size_t))
1079 GFC_INTEGER_LARGEST n = 0;
1080 int w, m, digits, nsign, nzero, nblank;
1081 char *p;
1082 const char *q;
1083 sign_t sign;
1084 char itoa_buf[GFC_BTOA_BUF_SIZE];
1086 w = f->u.integer.w;
1087 m = f->u.integer.m;
1089 n = extract_int (source, len);
1091 /* Special case: */
1093 if (m == 0 && n == 0)
1095 if (w == 0)
1096 w = 1;
1098 p = write_block (dtp, w);
1099 if (p == NULL)
1100 return;
1102 memset (p, ' ', w);
1103 goto done;
1106 sign = calculate_sign (dtp, n < 0);
1107 if (n < 0)
1108 n = -n;
1110 nsign = sign == SIGN_NONE ? 0 : 1;
1111 q = conv (n, itoa_buf, sizeof (itoa_buf));
1113 digits = strlen (q);
1115 /* Select a width if none was specified. The idea here is to always
1116 print something. */
1118 if (w == 0)
1119 w = ((digits < m) ? m : digits) + nsign;
1121 p = write_block (dtp, w);
1122 if (p == NULL)
1123 return;
1125 nzero = 0;
1126 if (digits < m)
1127 nzero = m - digits;
1129 /* See if things will work. */
1131 nblank = w - (nsign + nzero + digits);
1133 if (nblank < 0)
1135 star_fill (p, w);
1136 goto done;
1139 memset (p, ' ', nblank);
1140 p += nblank;
1142 switch (sign)
1144 case SIGN_PLUS:
1145 *p++ = '+';
1146 break;
1147 case SIGN_MINUS:
1148 *p++ = '-';
1149 break;
1150 case SIGN_NONE:
1151 break;
1154 memset (p, '0', nzero);
1155 p += nzero;
1157 memcpy (p, q, digits);
1159 done:
1160 return;
1164 /* Convert unsigned octal to ascii. */
1166 static const char *
1167 otoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
1169 char *p;
1171 assert (len >= GFC_OTOA_BUF_SIZE);
1173 if (n == 0)
1174 return "0";
1176 p = buffer + GFC_OTOA_BUF_SIZE - 1;
1177 *p = '\0';
1179 while (n != 0)
1181 *--p = '0' + (n & 7);
1182 n >>= 3;
1185 return p;
1189 /* Convert unsigned binary to ascii. */
1191 static const char *
1192 btoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
1194 char *p;
1196 assert (len >= GFC_BTOA_BUF_SIZE);
1198 if (n == 0)
1199 return "0";
1201 p = buffer + GFC_BTOA_BUF_SIZE - 1;
1202 *p = '\0';
1204 while (n != 0)
1206 *--p = '0' + (n & 1);
1207 n >>= 1;
1210 return p;
1214 void
1215 write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1217 write_decimal (dtp, f, p, len, (void *) gfc_itoa);
1221 void
1222 write_b (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1224 write_int (dtp, f, p, len, btoa);
1228 void
1229 write_o (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1231 write_int (dtp, f, p, len, otoa);
1234 void
1235 write_z (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1237 write_int (dtp, f, p, len, xtoa);
1241 void
1242 write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1244 write_float (dtp, f, p, len);
1248 void
1249 write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1251 write_float (dtp, f, p, len);
1255 void
1256 write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1258 write_float (dtp, f, p, len);
1262 void
1263 write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1265 write_float (dtp, f, p, len);
1269 void
1270 write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1272 write_float (dtp, f, p, len);
1276 /* Take care of the X/TR descriptor. */
1278 void
1279 write_x (st_parameter_dt *dtp, int len, int nspaces)
1281 char *p;
1283 p = write_block (dtp, len);
1284 if (p == NULL)
1285 return;
1287 if (nspaces > 0)
1288 memset (&p[len - nspaces], ' ', nspaces);
1292 /* List-directed writing. */
1295 /* Write a single character to the output. Returns nonzero if
1296 something goes wrong. */
1298 static int
1299 write_char (st_parameter_dt *dtp, char c)
1301 char *p;
1303 p = write_block (dtp, 1);
1304 if (p == NULL)
1305 return 1;
1307 *p = c;
1309 return 0;
1313 /* Write a list-directed logical value. */
1315 static void
1316 write_logical (st_parameter_dt *dtp, const char *source, int length)
1318 write_char (dtp, extract_int (source, length) ? 'T' : 'F');
1322 /* Write a list-directed integer value. */
1324 static void
1325 write_integer (st_parameter_dt *dtp, const char *source, int length)
1327 char *p;
1328 const char *q;
1329 int digits;
1330 int width;
1331 char itoa_buf[GFC_ITOA_BUF_SIZE];
1333 q = gfc_itoa (extract_int (source, length), itoa_buf, sizeof (itoa_buf));
1335 switch (length)
1337 case 1:
1338 width = 4;
1339 break;
1341 case 2:
1342 width = 6;
1343 break;
1345 case 4:
1346 width = 11;
1347 break;
1349 case 8:
1350 width = 20;
1351 break;
1353 default:
1354 width = 0;
1355 break;
1358 digits = strlen (q);
1360 if (width < digits)
1361 width = digits;
1362 p = write_block (dtp, width);
1363 if (p == NULL)
1364 return;
1365 if (dtp->u.p.no_leading_blank)
1367 memcpy (p, q, digits);
1368 memset (p + digits, ' ', width - digits);
1370 else
1372 memset (p, ' ', width - digits);
1373 memcpy (p + width - digits, q, digits);
1378 /* Write a list-directed string. We have to worry about delimiting
1379 the strings if the file has been opened in that mode. */
1381 static void
1382 write_character (st_parameter_dt *dtp, const char *source, int length)
1384 int i, extra;
1385 char *p, d;
1387 switch (dtp->u.p.current_unit->flags.delim)
1389 case DELIM_APOSTROPHE:
1390 d = '\'';
1391 break;
1392 case DELIM_QUOTE:
1393 d = '"';
1394 break;
1395 default:
1396 d = ' ';
1397 break;
1400 if (d == ' ')
1401 extra = 0;
1402 else
1404 extra = 2;
1406 for (i = 0; i < length; i++)
1407 if (source[i] == d)
1408 extra++;
1411 p = write_block (dtp, length + extra);
1412 if (p == NULL)
1413 return;
1415 if (d == ' ')
1416 memcpy (p, source, length);
1417 else
1419 *p++ = d;
1421 for (i = 0; i < length; i++)
1423 *p++ = source[i];
1424 if (source[i] == d)
1425 *p++ = d;
1428 *p = d;
1433 /* Output a real number with default format.
1434 This is 1PG14.7E2 for REAL(4), 1PG23.15E3 for REAL(8),
1435 1PG28.19E4 for REAL(10) and 1PG43.34E4 for REAL(16). */
1437 static void
1438 write_real (st_parameter_dt *dtp, const char *source, int length)
1440 fnode f ;
1441 int org_scale = dtp->u.p.scale_factor;
1442 f.format = FMT_G;
1443 dtp->u.p.scale_factor = 1;
1444 switch (length)
1446 case 4:
1447 f.u.real.w = 14;
1448 f.u.real.d = 7;
1449 f.u.real.e = 2;
1450 break;
1451 case 8:
1452 f.u.real.w = 23;
1453 f.u.real.d = 15;
1454 f.u.real.e = 3;
1455 break;
1456 case 10:
1457 f.u.real.w = 28;
1458 f.u.real.d = 19;
1459 f.u.real.e = 4;
1460 break;
1461 case 16:
1462 f.u.real.w = 43;
1463 f.u.real.d = 34;
1464 f.u.real.e = 4;
1465 break;
1466 default:
1467 internal_error (&dtp->common, "bad real kind");
1468 break;
1470 write_float (dtp, &f, source , length);
1471 dtp->u.p.scale_factor = org_scale;
1475 static void
1476 write_complex (st_parameter_dt *dtp, const char *source, int kind, size_t size)
1478 if (write_char (dtp, '('))
1479 return;
1480 write_real (dtp, source, kind);
1482 if (write_char (dtp, ','))
1483 return;
1484 write_real (dtp, source + size / 2, kind);
1486 write_char (dtp, ')');
1490 /* Write the separator between items. */
1492 static void
1493 write_separator (st_parameter_dt *dtp)
1495 char *p;
1497 p = write_block (dtp, options.separator_len);
1498 if (p == NULL)
1499 return;
1501 memcpy (p, options.separator, options.separator_len);
1505 /* Write an item with list formatting.
1506 TODO: handle skipping to the next record correctly, particularly
1507 with strings. */
1509 static void
1510 list_formatted_write_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
1511 size_t size)
1513 if (dtp->u.p.current_unit == NULL)
1514 return;
1516 if (dtp->u.p.first_item)
1518 dtp->u.p.first_item = 0;
1519 write_char (dtp, ' ');
1521 else
1523 if (type != BT_CHARACTER || !dtp->u.p.char_flag ||
1524 dtp->u.p.current_unit->flags.delim != DELIM_NONE)
1525 write_separator (dtp);
1528 switch (type)
1530 case BT_INTEGER:
1531 write_integer (dtp, p, kind);
1532 break;
1533 case BT_LOGICAL:
1534 write_logical (dtp, p, kind);
1535 break;
1536 case BT_CHARACTER:
1537 write_character (dtp, p, kind);
1538 break;
1539 case BT_REAL:
1540 write_real (dtp, p, kind);
1541 break;
1542 case BT_COMPLEX:
1543 write_complex (dtp, p, kind, size);
1544 break;
1545 default:
1546 internal_error (&dtp->common, "list_formatted_write(): Bad type");
1549 dtp->u.p.char_flag = (type == BT_CHARACTER);
1553 void
1554 list_formatted_write (st_parameter_dt *dtp, bt type, void *p, int kind,
1555 size_t size, size_t nelems)
1557 size_t elem;
1558 char *tmp;
1560 tmp = (char *) p;
1562 /* Big loop over all the elements. */
1563 for (elem = 0; elem < nelems; elem++)
1565 dtp->u.p.item_count++;
1566 list_formatted_write_scalar (dtp, type, tmp + size*elem, kind, size);
1570 /* NAMELIST OUTPUT
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. */
1588 /* A generous estimate of the number of characters needed to print
1589 repeat counts and indices, including commas, asterices and brackets. */
1591 #define NML_DIGITS 20
1593 static namelist_info *
1594 nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
1595 namelist_info * base, char * base_name)
1597 int rep_ctr;
1598 int num;
1599 int nml_carry;
1600 index_type len;
1601 index_type obj_size;
1602 index_type nelem;
1603 index_type dim_i;
1604 index_type clen;
1605 index_type elem_ctr;
1606 index_type obj_name_len;
1607 void * p ;
1608 char cup;
1609 char * obj_name;
1610 char * ext_name;
1611 char rep_buff[NML_DIGITS];
1612 namelist_info * cmp;
1613 namelist_info * retval = obj->next;
1615 /* Write namelist variable names in upper case. If a derived type,
1616 nothing is output. If a component, base and base_name are set. */
1618 if (obj->type != GFC_DTYPE_DERIVED)
1620 #ifdef HAVE_CRLF
1621 write_character (dtp, "\r\n ", 3);
1622 #else
1623 write_character (dtp, "\n ", 2);
1624 #endif
1625 len = 0;
1626 if (base)
1628 len =strlen (base->var_name);
1629 for (dim_i = 0; dim_i < (index_type) strlen (base_name); dim_i++)
1631 cup = toupper (base_name[dim_i]);
1632 write_character (dtp, &cup, 1);
1635 for (dim_i =len; dim_i < (index_type) strlen (obj->var_name); dim_i++)
1637 cup = toupper (obj->var_name[dim_i]);
1638 write_character (dtp, &cup, 1);
1640 write_character (dtp, "=", 1);
1643 /* Counts the number of data output on a line, including names. */
1645 num = 1;
1647 len = obj->len;
1649 switch (obj->type)
1652 case GFC_DTYPE_REAL:
1653 obj_size = size_from_real_kind (len);
1654 break;
1656 case GFC_DTYPE_COMPLEX:
1657 obj_size = size_from_complex_kind (len);
1658 break;
1660 case GFC_DTYPE_CHARACTER:
1661 obj_size = obj->string_length;
1662 break;
1664 default:
1665 obj_size = len;
1668 if (obj->var_rank)
1669 obj_size = obj->size;
1671 /* Set the index vector and count the number of elements. */
1673 nelem = 1;
1674 for (dim_i=0; dim_i < obj->var_rank; dim_i++)
1676 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1677 nelem = nelem * (obj->dim[dim_i].ubound + 1 - obj->dim[dim_i].lbound);
1680 /* Main loop to output the data held in the object. */
1682 rep_ctr = 1;
1683 for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
1686 /* Build the pointer to the data value. The offset is passed by
1687 recursive calls to this function for arrays of derived types.
1688 Is NULL otherwise. */
1690 p = (void *)(obj->mem_pos + elem_ctr * obj_size);
1691 p += offset;
1693 /* Check for repeat counts of intrinsic types. */
1695 if ((elem_ctr < (nelem - 1)) &&
1696 (obj->type != GFC_DTYPE_DERIVED) &&
1697 !memcmp (p, (void*)(p + obj_size ), obj_size ))
1699 rep_ctr++;
1702 /* Execute a repeated output. Note the flag no_leading_blank that
1703 is used in the functions used to output the intrinsic types. */
1705 else
1707 if (rep_ctr > 1)
1709 st_sprintf(rep_buff, " %d*", rep_ctr);
1710 write_character (dtp, rep_buff, strlen (rep_buff));
1711 dtp->u.p.no_leading_blank = 1;
1713 num++;
1715 /* Output the data, if an intrinsic type, or recurse into this
1716 routine to treat derived types. */
1718 switch (obj->type)
1721 case GFC_DTYPE_INTEGER:
1722 write_integer (dtp, p, len);
1723 break;
1725 case GFC_DTYPE_LOGICAL:
1726 write_logical (dtp, p, len);
1727 break;
1729 case GFC_DTYPE_CHARACTER:
1730 if (dtp->u.p.nml_delim)
1731 write_character (dtp, &dtp->u.p.nml_delim, 1);
1732 write_character (dtp, p, obj->string_length);
1733 if (dtp->u.p.nml_delim)
1734 write_character (dtp, &dtp->u.p.nml_delim, 1);
1735 break;
1737 case GFC_DTYPE_REAL:
1738 write_real (dtp, p, len);
1739 break;
1741 case GFC_DTYPE_COMPLEX:
1742 dtp->u.p.no_leading_blank = 0;
1743 num++;
1744 write_complex (dtp, p, len, obj_size);
1745 break;
1747 case GFC_DTYPE_DERIVED:
1749 /* To treat a derived type, we need to build two strings:
1750 ext_name = the name, including qualifiers that prepends
1751 component names in the output - passed to
1752 nml_write_obj.
1753 obj_name = the derived type name with no qualifiers but %
1754 appended. This is used to identify the
1755 components. */
1757 /* First ext_name => get length of all possible components */
1759 ext_name = (char*)get_mem ( (base_name ? strlen (base_name) : 0)
1760 + (base ? strlen (base->var_name) : 0)
1761 + strlen (obj->var_name)
1762 + obj->var_rank * NML_DIGITS
1763 + 1);
1765 strcpy(ext_name, base_name ? base_name : "");
1766 clen = base ? strlen (base->var_name) : 0;
1767 strcat (ext_name, obj->var_name + clen);
1769 /* Append the qualifier. */
1771 for (dim_i = 0; dim_i < obj->var_rank; dim_i++)
1773 strcat (ext_name, dim_i ? "" : "(");
1774 clen = strlen (ext_name);
1775 st_sprintf (ext_name + clen, "%d", (int) obj->ls[dim_i].idx);
1776 strcat (ext_name, (dim_i == obj->var_rank - 1) ? ")" : ",");
1779 /* Now obj_name. */
1781 obj_name_len = strlen (obj->var_name) + 1;
1782 obj_name = get_mem (obj_name_len+1);
1783 strcpy (obj_name, obj->var_name);
1784 strcat (obj_name, "%");
1786 /* Now loop over the components. Update the component pointer
1787 with the return value from nml_write_obj => this loop jumps
1788 past nested derived types. */
1790 for (cmp = obj->next;
1791 cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
1792 cmp = retval)
1794 retval = nml_write_obj (dtp, cmp,
1795 (index_type)(p - obj->mem_pos),
1796 obj, ext_name);
1799 free_mem (obj_name);
1800 free_mem (ext_name);
1801 goto obj_loop;
1803 default:
1804 internal_error (&dtp->common, "Bad type for namelist write");
1807 /* Reset the leading blank suppression, write a comma and, if 5
1808 values have been output, write a newline and advance to column
1809 2. Reset the repeat counter. */
1811 dtp->u.p.no_leading_blank = 0;
1812 write_character (dtp, ",", 1);
1813 if (num > 5)
1815 num = 0;
1816 #ifdef HAVE_CRLF
1817 write_character (dtp, "\r\n ", 3);
1818 #else
1819 write_character (dtp, "\n ", 2);
1820 #endif
1822 rep_ctr = 1;
1825 /* Cycle through and increment the index vector. */
1827 obj_loop:
1829 nml_carry = 1;
1830 for (dim_i = 0; nml_carry && (dim_i < obj->var_rank); dim_i++)
1832 obj->ls[dim_i].idx += nml_carry ;
1833 nml_carry = 0;
1834 if (obj->ls[dim_i].idx > (ssize_t)obj->dim[dim_i].ubound)
1836 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1837 nml_carry = 1;
1842 /* Return a pointer beyond the furthest object accessed. */
1844 return retval;
1847 /* This is the entry function for namelist writes. It outputs the name
1848 of the namelist and iterates through the namelist by calls to
1849 nml_write_obj. The call below has dummys in the arguments used in
1850 the treatment of derived types. */
1852 void
1853 namelist_write (st_parameter_dt *dtp)
1855 namelist_info * t1, *t2, *dummy = NULL;
1856 index_type i;
1857 index_type dummy_offset = 0;
1858 char c;
1859 char * dummy_name = NULL;
1860 unit_delim tmp_delim;
1862 /* Set the delimiter for namelist output. */
1864 tmp_delim = dtp->u.p.current_unit->flags.delim;
1865 dtp->u.p.current_unit->flags.delim = DELIM_NONE;
1866 switch (tmp_delim)
1868 case (DELIM_QUOTE):
1869 dtp->u.p.nml_delim = '"';
1870 break;
1872 case (DELIM_APOSTROPHE):
1873 dtp->u.p.nml_delim = '\'';
1874 break;
1876 default:
1877 dtp->u.p.nml_delim = '\0';
1878 break;
1881 write_character (dtp, "&", 1);
1883 /* Write namelist name in upper case - f95 std. */
1885 for (i = 0 ;i < dtp->namelist_name_len ;i++ )
1887 c = toupper (dtp->namelist_name[i]);
1888 write_character (dtp, &c ,1);
1891 if (dtp->u.p.ionml != NULL)
1893 t1 = dtp->u.p.ionml;
1894 while (t1 != NULL)
1896 t2 = t1;
1897 t1 = nml_write_obj (dtp, t2, dummy_offset, dummy, dummy_name);
1900 #ifdef HAVE_CRLF
1901 write_character (dtp, " /\r\n", 5);
1902 #else
1903 write_character (dtp, " /\n", 4);
1904 #endif
1906 /* Recover the original delimiter. */
1908 dtp->u.p.current_unit->flags.delim = tmp_delim;
1911 #undef NML_DIGITS