2006-03-22 Thomas Koenig <Thomas.Koenig@onlien.de>
[official-gcc.git] / libgfortran / io / write.c
blobedd2933c3de1fc7ceae3266068f1d562bec49315
1 /* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
3 Namelist output contibuted 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 p = write_block (dtp, wlen);
58 if (p == NULL)
59 return;
61 if (wlen < len)
62 memcpy (p, source, wlen);
63 else
65 memset (p, ' ', wlen - len);
66 memcpy (p + wlen - len, source, len);
70 static GFC_INTEGER_LARGEST
71 extract_int (const void *p, int len)
73 GFC_INTEGER_LARGEST i = 0;
75 if (p == NULL)
76 return i;
78 switch (len)
80 case 1:
82 GFC_INTEGER_1 tmp;
83 memcpy ((void *) &tmp, p, len);
84 i = tmp;
86 break;
87 case 2:
89 GFC_INTEGER_2 tmp;
90 memcpy ((void *) &tmp, p, len);
91 i = tmp;
93 break;
94 case 4:
96 GFC_INTEGER_4 tmp;
97 memcpy ((void *) &tmp, p, len);
98 i = tmp;
100 break;
101 case 8:
103 GFC_INTEGER_8 tmp;
104 memcpy ((void *) &tmp, p, len);
105 i = tmp;
107 break;
108 #ifdef HAVE_GFC_INTEGER_16
109 case 16:
111 GFC_INTEGER_16 tmp;
112 memcpy ((void *) &tmp, p, len);
113 i = tmp;
115 break;
116 #endif
117 default:
118 internal_error (NULL, "bad integer kind");
121 return i;
124 static GFC_UINTEGER_LARGEST
125 extract_uint (const void *p, int len)
127 GFC_UINTEGER_LARGEST i = 0;
129 if (p == NULL)
130 return i;
132 switch (len)
134 case 1:
136 GFC_INTEGER_1 tmp;
137 memcpy ((void *) &tmp, p, len);
138 i = (GFC_UINTEGER_1) tmp;
140 break;
141 case 2:
143 GFC_INTEGER_2 tmp;
144 memcpy ((void *) &tmp, p, len);
145 i = (GFC_UINTEGER_2) tmp;
147 break;
148 case 4:
150 GFC_INTEGER_4 tmp;
151 memcpy ((void *) &tmp, p, len);
152 i = (GFC_UINTEGER_4) tmp;
154 break;
155 case 8:
157 GFC_INTEGER_8 tmp;
158 memcpy ((void *) &tmp, p, len);
159 i = (GFC_UINTEGER_8) tmp;
161 break;
162 #ifdef HAVE_GFC_INTEGER_16
163 case 16:
165 GFC_INTEGER_16 tmp;
166 memcpy ((void *) &tmp, p, len);
167 i = (GFC_UINTEGER_16) tmp;
169 break;
170 #endif
171 default:
172 internal_error (NULL, "bad integer kind");
175 return i;
178 static GFC_REAL_LARGEST
179 extract_real (const void *p, int len)
181 GFC_REAL_LARGEST i = 0;
182 switch (len)
184 case 4:
186 GFC_REAL_4 tmp;
187 memcpy ((void *) &tmp, p, len);
188 i = tmp;
190 break;
191 case 8:
193 GFC_REAL_8 tmp;
194 memcpy ((void *) &tmp, p, len);
195 i = tmp;
197 break;
198 #ifdef HAVE_GFC_REAL_10
199 case 10:
201 GFC_REAL_10 tmp;
202 memcpy ((void *) &tmp, p, len);
203 i = tmp;
205 break;
206 #endif
207 #ifdef HAVE_GFC_REAL_16
208 case 16:
210 GFC_REAL_16 tmp;
211 memcpy ((void *) &tmp, p, len);
212 i = tmp;
214 break;
215 #endif
216 default:
217 internal_error (NULL, "bad real kind");
219 return i;
223 /* Given a flag that indicate if a value is negative or not, return a
224 sign_t that gives the sign that we need to produce. */
226 static sign_t
227 calculate_sign (st_parameter_dt *dtp, int negative_flag)
229 sign_t s = SIGN_NONE;
231 if (negative_flag)
232 s = SIGN_MINUS;
233 else
234 switch (dtp->u.p.sign_status)
236 case SIGN_SP:
237 s = SIGN_PLUS;
238 break;
239 case SIGN_SS:
240 s = SIGN_NONE;
241 break;
242 case SIGN_S:
243 s = options.optional_plus ? SIGN_PLUS : SIGN_NONE;
244 break;
247 return s;
251 /* Returns the value of 10**d. */
253 static GFC_REAL_LARGEST
254 calculate_exp (int d)
256 int i;
257 GFC_REAL_LARGEST r = 1.0;
259 for (i = 0; i< (d >= 0 ? d : -d); i++)
260 r *= 10;
262 r = (d >= 0) ? r : 1.0 / r;
264 return r;
268 /* Generate corresponding I/O format for FMT_G output.
269 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
270 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
272 Data Magnitude Equivalent Conversion
273 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
274 m = 0 F(w-n).(d-1), n' '
275 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
276 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
277 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
278 ................ ..........
279 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
280 m >= 10**d-0.5 Ew.d[Ee]
282 notes: for Gw.d , n' ' means 4 blanks
283 for Gw.dEe, n' ' means e+2 blanks */
285 static fnode *
286 calculate_G_format (st_parameter_dt *dtp, const fnode *f,
287 GFC_REAL_LARGEST value, int *num_blank)
289 int e = f->u.real.e;
290 int d = f->u.real.d;
291 int w = f->u.real.w;
292 fnode *newf;
293 GFC_REAL_LARGEST m, exp_d;
294 int low, high, mid;
295 int ubound, lbound;
297 newf = get_mem (sizeof (fnode));
299 /* Absolute value. */
300 m = (value > 0.0) ? value : -value;
302 /* In case of the two data magnitude ranges,
303 generate E editing, Ew.d[Ee]. */
304 exp_d = calculate_exp (d);
305 if ((m > 0.0 && m < 0.1 - 0.05 / exp_d) || (m >= exp_d - 0.5 ) ||
306 ((m == 0.0) && !(compile_options.allow_std & GFC_STD_F2003)))
308 newf->format = FMT_E;
309 newf->u.real.w = w;
310 newf->u.real.d = d;
311 newf->u.real.e = e;
312 *num_blank = 0;
313 return newf;
316 /* Use binary search to find the data magnitude range. */
317 mid = 0;
318 low = 0;
319 high = d + 1;
320 lbound = 0;
321 ubound = d + 1;
323 while (low <= high)
325 GFC_REAL_LARGEST temp;
326 mid = (low + high) / 2;
328 /* 0.1 * 10**mid - 0.5 * 10**(mid-d-1) */
329 temp = 0.1 * calculate_exp (mid) - 0.5 * calculate_exp (mid - d - 1);
331 if (m < temp)
333 ubound = mid;
334 if (ubound == lbound + 1)
335 break;
336 high = mid - 1;
338 else if (m > temp)
340 lbound = mid;
341 if (ubound == lbound + 1)
343 mid ++;
344 break;
346 low = mid + 1;
348 else
349 break;
352 /* Pad with blanks where the exponent would be. */
353 if (e < 0)
354 *num_blank = 4;
355 else
356 *num_blank = e + 2;
358 /* Generate the F editing. F(w-n).(-(mid-d-1)), n' '. */
359 newf->format = FMT_F;
360 newf->u.real.w = f->u.real.w - *num_blank;
362 /* Special case. */
363 if (m == 0.0)
364 newf->u.real.d = d - 1;
365 else
366 newf->u.real.d = - (mid - d - 1);
368 /* For F editing, the scale factor is ignored. */
369 dtp->u.p.scale_factor = 0;
370 return newf;
374 /* Output a real number according to its format which is FMT_G free. */
376 static void
377 output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
379 /* This must be large enough to accurately hold any value. */
380 char buffer[32];
381 char *out;
382 char *digits;
383 int e;
384 char expchar;
385 format_token ft;
386 int w;
387 int d;
388 int edigits;
389 int ndigits;
390 /* Number of digits before the decimal point. */
391 int nbefore;
392 /* Number of zeros after the decimal point. */
393 int nzero;
394 /* Number of digits after the decimal point. */
395 int nafter;
396 /* Number of zeros after the decimal point, whatever the precision. */
397 int nzero_real;
398 int leadzero;
399 int nblanks;
400 int i;
401 sign_t sign;
402 double abslog;
404 ft = f->format;
405 w = f->u.real.w;
406 d = f->u.real.d;
408 nzero_real = -1;
411 /* We should always know the field width and precision. */
412 if (d < 0)
413 internal_error (&dtp->common, "Unspecified precision");
415 /* Use sprintf to print the number in the format +D.DDDDe+ddd
416 For an N digit exponent, this gives us (32-6)-N digits after the
417 decimal point, plus another one before the decimal point. */
418 sign = calculate_sign (dtp, value < 0.0);
419 if (value < 0)
420 value = -value;
422 /* Printf always prints at least two exponent digits. */
423 if (value == 0)
424 edigits = 2;
425 else
427 #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
428 abslog = fabs((double) log10l(value));
429 #else
430 abslog = fabs(log10(value));
431 #endif
432 if (abslog < 100)
433 edigits = 2;
434 else
435 edigits = 1 + (int) log10(abslog);
438 if (ft == FMT_F || ft == FMT_EN
439 || ((ft == FMT_D || ft == FMT_E) && dtp->u.p.scale_factor != 0))
441 /* Always convert at full precision to avoid double rounding. */
442 ndigits = 27 - edigits;
444 else
446 /* We know the number of digits, so can let printf do the rounding
447 for us. */
448 if (ft == FMT_ES)
449 ndigits = d + 1;
450 else
451 ndigits = d;
452 if (ndigits > 27 - edigits)
453 ndigits = 27 - edigits;
456 /* # The result will always contain a decimal point, even if no
457 * digits follow it
459 * - The converted value is to be left adjusted on the field boundary
461 * + A sign (+ or -) always be placed before a number
463 * 31 minimum field width
465 * * (ndigits-1) is used as the precision
467 * e format: [-]d.ddde±dd where there is one digit before the
468 * decimal-point character and the number of digits after it is
469 * equal to the precision. The exponent always contains at least two
470 * digits; if the value is zero, the exponent is 00.
472 sprintf (buffer, "%+-#31.*" GFC_REAL_LARGEST_FORMAT "e",
473 ndigits - 1, value);
475 /* Check the resulting string has punctuation in the correct places. */
476 if (buffer[2] != '.' || buffer[ndigits + 2] != 'e')
477 internal_error (&dtp->common, "printf is broken");
479 /* Read the exponent back in. */
480 e = atoi (&buffer[ndigits + 3]) + 1;
482 /* Make sure zero comes out as 0.0e0. */
483 if (value == 0.0)
484 e = 0;
486 /* Normalize the fractional component. */
487 buffer[2] = buffer[1];
488 digits = &buffer[2];
490 /* Figure out where to place the decimal point. */
491 switch (ft)
493 case FMT_F:
494 nbefore = e + dtp->u.p.scale_factor;
495 if (nbefore < 0)
497 nzero = -nbefore;
498 nzero_real = nzero;
499 if (nzero > d)
500 nzero = d;
501 nafter = d - nzero;
502 nbefore = 0;
504 else
506 nzero = 0;
507 nafter = d;
509 expchar = 0;
510 break;
512 case FMT_E:
513 case FMT_D:
514 i = dtp->u.p.scale_factor;
515 if (value != 0.0)
516 e -= i;
517 if (i < 0)
519 nbefore = 0;
520 nzero = -i;
521 nafter = d + i;
523 else if (i > 0)
525 nbefore = i;
526 nzero = 0;
527 nafter = (d - i) + 1;
529 else /* i == 0 */
531 nbefore = 0;
532 nzero = 0;
533 nafter = d;
536 if (ft == FMT_E)
537 expchar = 'E';
538 else
539 expchar = 'D';
540 break;
542 case FMT_EN:
543 /* The exponent must be a multiple of three, with 1-3 digits before
544 the decimal point. */
545 if (value != 0.0)
546 e--;
547 if (e >= 0)
548 nbefore = e % 3;
549 else
551 nbefore = (-e) % 3;
552 if (nbefore != 0)
553 nbefore = 3 - nbefore;
555 e -= nbefore;
556 nbefore++;
557 nzero = 0;
558 nafter = d;
559 expchar = 'E';
560 break;
562 case FMT_ES:
563 if (value != 0.0)
564 e--;
565 nbefore = 1;
566 nzero = 0;
567 nafter = d;
568 expchar = 'E';
569 break;
571 default:
572 /* Should never happen. */
573 internal_error (&dtp->common, "Unexpected format token");
576 /* Round the value. */
577 if (nbefore + nafter == 0)
579 ndigits = 0;
580 if (nzero_real == d && digits[0] >= '5')
582 /* We rounded to zero but shouldn't have */
583 nzero--;
584 nafter = 1;
585 digits[0] = '1';
586 ndigits = 1;
589 else if (nbefore + nafter < ndigits)
591 ndigits = nbefore + nafter;
592 i = ndigits;
593 if (digits[i] >= '5')
595 /* Propagate the carry. */
596 for (i--; i >= 0; i--)
598 if (digits[i] != '9')
600 digits[i]++;
601 break;
603 digits[i] = '0';
606 if (i < 0)
608 /* The carry overflowed. Fortunately we have some spare space
609 at the start of the buffer. We may discard some digits, but
610 this is ok because we already know they are zero. */
611 digits--;
612 digits[0] = '1';
613 if (ft == FMT_F)
615 if (nzero > 0)
617 nzero--;
618 nafter++;
620 else
621 nbefore++;
623 else if (ft == FMT_EN)
625 nbefore++;
626 if (nbefore == 4)
628 nbefore = 1;
629 e += 3;
632 else
633 e++;
638 /* Calculate the format of the exponent field. */
639 if (expchar)
641 edigits = 1;
642 for (i = abs (e); i >= 10; i /= 10)
643 edigits++;
645 if (f->u.real.e < 0)
647 /* Width not specified. Must be no more than 3 digits. */
648 if (e > 999 || e < -999)
649 edigits = -1;
650 else
652 edigits = 4;
653 if (e > 99 || e < -99)
654 expchar = ' ';
657 else
659 /* Exponent width specified, check it is wide enough. */
660 if (edigits > f->u.real.e)
661 edigits = -1;
662 else
663 edigits = f->u.real.e + 2;
666 else
667 edigits = 0;
669 /* Pick a field size if none was specified. */
670 if (w <= 0)
671 w = nbefore + nzero + nafter + (sign != SIGN_NONE ? 2 : 1);
673 /* Create the ouput buffer. */
674 out = write_block (dtp, w);
675 if (out == NULL)
676 return;
678 /* Zero values always output as positive, even if the value was negative
679 before rounding. */
680 for (i = 0; i < ndigits; i++)
682 if (digits[i] != '0')
683 break;
685 if (i == ndigits)
686 sign = calculate_sign (dtp, 0);
688 /* Work out how much padding is needed. */
689 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
690 if (sign != SIGN_NONE)
691 nblanks--;
693 /* Check the value fits in the specified field width. */
694 if (nblanks < 0 || edigits == -1)
696 star_fill (out, w);
697 return;
700 /* See if we have space for a zero before the decimal point. */
701 if (nbefore == 0 && nblanks > 0)
703 leadzero = 1;
704 nblanks--;
706 else
707 leadzero = 0;
709 /* Pad to full field width. */
712 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
714 memset (out, ' ', nblanks);
715 out += nblanks;
718 /* Output the initial sign (if any). */
719 if (sign == SIGN_PLUS)
720 *(out++) = '+';
721 else if (sign == SIGN_MINUS)
722 *(out++) = '-';
724 /* Output an optional leading zero. */
725 if (leadzero)
726 *(out++) = '0';
728 /* Output the part before the decimal point, padding with zeros. */
729 if (nbefore > 0)
731 if (nbefore > ndigits)
732 i = ndigits;
733 else
734 i = nbefore;
736 memcpy (out, digits, i);
737 while (i < nbefore)
738 out[i++] = '0';
740 digits += i;
741 ndigits -= i;
742 out += nbefore;
744 /* Output the decimal point. */
745 *(out++) = '.';
747 /* Output leading zeros after the decimal point. */
748 if (nzero > 0)
750 for (i = 0; i < nzero; i++)
751 *(out++) = '0';
754 /* Output digits after the decimal point, padding with zeros. */
755 if (nafter > 0)
757 if (nafter > ndigits)
758 i = ndigits;
759 else
760 i = nafter;
762 memcpy (out, digits, i);
763 while (i < nafter)
764 out[i++] = '0';
766 digits += i;
767 ndigits -= i;
768 out += nafter;
771 /* Output the exponent. */
772 if (expchar)
774 if (expchar != ' ')
776 *(out++) = expchar;
777 edigits--;
779 #if HAVE_SNPRINTF
780 snprintf (buffer, 32, "%+0*d", edigits, e);
781 #else
782 sprintf (buffer, "%+0*d", edigits, e);
783 #endif
784 memcpy (out, buffer, edigits);
787 if (dtp->u.p.no_leading_blank)
789 out += edigits;
790 memset( out , ' ' , nblanks );
791 dtp->u.p.no_leading_blank = 0;
796 void
797 write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
799 char *p;
800 GFC_INTEGER_LARGEST n;
802 p = write_block (dtp, f->u.w);
803 if (p == NULL)
804 return;
806 memset (p, ' ', f->u.w - 1);
807 n = extract_int (source, len);
808 p[f->u.w - 1] = (n) ? 'T' : 'F';
811 /* Output a real number according to its format. */
813 static void
814 write_float (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
816 GFC_REAL_LARGEST n;
817 int nb =0, res, save_scale_factor;
818 char * p, fin;
819 fnode *f2 = NULL;
821 n = extract_real (source, len);
823 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
825 res = isfinite (n);
826 if (res == 0)
828 nb = f->u.real.w;
830 /* If the field width is zero, the processor must select a width
831 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
833 if (nb == 0) nb = 4;
834 p = write_block (dtp, nb);
835 if (p == NULL)
836 return;
837 if (nb < 3)
839 memset (p, '*',nb);
840 return;
843 memset(p, ' ', nb);
844 res = !isnan (n);
845 if (res != 0)
847 if (signbit(n))
850 /* If the sign is negative and the width is 3, there is
851 insufficient room to output '-Inf', so output asterisks */
853 if (nb == 3)
855 memset (p, '*',nb);
856 return;
859 /* The negative sign is mandatory */
861 fin = '-';
863 else
865 /* The positive sign is optional, but we output it for
866 consistency */
868 fin = '+';
870 if (nb > 8)
872 /* We have room, so output 'Infinity' */
874 memcpy(p + nb - 8, "Infinity", 8);
875 else
877 /* For the case of width equals 8, there is not enough room
878 for the sign and 'Infinity' so we go with 'Inf' */
880 memcpy(p + nb - 3, "Inf", 3);
881 if (nb < 9 && nb > 3)
882 p[nb - 4] = fin; /* Put the sign in front of Inf */
883 else if (nb > 8)
884 p[nb - 9] = fin; /* Put the sign in front of Infinity */
886 else
887 memcpy(p + nb - 3, "NaN", 3);
888 return;
892 if (f->format != FMT_G)
893 output_float (dtp, f, n);
894 else
896 save_scale_factor = dtp->u.p.scale_factor;
897 f2 = calculate_G_format (dtp, f, n, &nb);
898 output_float (dtp, f2, n);
899 dtp->u.p.scale_factor = save_scale_factor;
900 if (f2 != NULL)
901 free_mem(f2);
903 if (nb > 0)
905 p = write_block (dtp, nb);
906 if (p == NULL)
907 return;
908 memset (p, ' ', nb);
914 static void
915 write_int (st_parameter_dt *dtp, const fnode *f, const char *source, int len,
916 const char *(*conv) (GFC_UINTEGER_LARGEST, char *, size_t))
918 GFC_UINTEGER_LARGEST n = 0;
919 int w, m, digits, nzero, nblank;
920 char *p;
921 const char *q;
922 char itoa_buf[GFC_BTOA_BUF_SIZE];
924 w = f->u.integer.w;
925 m = f->u.integer.m;
927 n = extract_uint (source, len);
929 /* Special case: */
931 if (m == 0 && n == 0)
933 if (w == 0)
934 w = 1;
936 p = write_block (dtp, w);
937 if (p == NULL)
938 return;
940 memset (p, ' ', w);
941 goto done;
944 q = conv (n, itoa_buf, sizeof (itoa_buf));
945 digits = strlen (q);
947 /* Select a width if none was specified. The idea here is to always
948 print something. */
950 if (w == 0)
951 w = ((digits < m) ? m : digits);
953 p = write_block (dtp, w);
954 if (p == NULL)
955 return;
957 nzero = 0;
958 if (digits < m)
959 nzero = m - digits;
961 /* See if things will work. */
963 nblank = w - (nzero + digits);
965 if (nblank < 0)
967 star_fill (p, w);
968 goto done;
972 if (!dtp->u.p.no_leading_blank)
974 memset (p, ' ', nblank);
975 p += nblank;
976 memset (p, '0', nzero);
977 p += nzero;
978 memcpy (p, q, digits);
980 else
982 memset (p, '0', nzero);
983 p += nzero;
984 memcpy (p, q, digits);
985 p += digits;
986 memset (p, ' ', nblank);
987 dtp->u.p.no_leading_blank = 0;
990 done:
991 return;
994 static void
995 write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
996 int len,
997 const char *(*conv) (GFC_INTEGER_LARGEST, char *, size_t))
999 GFC_INTEGER_LARGEST n = 0;
1000 int w, m, digits, nsign, nzero, nblank;
1001 char *p;
1002 const char *q;
1003 sign_t sign;
1004 char itoa_buf[GFC_BTOA_BUF_SIZE];
1006 w = f->u.integer.w;
1007 m = f->u.integer.m;
1009 n = extract_int (source, len);
1011 /* Special case: */
1013 if (m == 0 && n == 0)
1015 if (w == 0)
1016 w = 1;
1018 p = write_block (dtp, w);
1019 if (p == NULL)
1020 return;
1022 memset (p, ' ', w);
1023 goto done;
1026 sign = calculate_sign (dtp, n < 0);
1027 if (n < 0)
1028 n = -n;
1030 nsign = sign == SIGN_NONE ? 0 : 1;
1031 q = conv (n, itoa_buf, sizeof (itoa_buf));
1033 digits = strlen (q);
1035 /* Select a width if none was specified. The idea here is to always
1036 print something. */
1038 if (w == 0)
1039 w = ((digits < m) ? m : digits) + nsign;
1041 p = write_block (dtp, w);
1042 if (p == NULL)
1043 return;
1045 nzero = 0;
1046 if (digits < m)
1047 nzero = m - digits;
1049 /* See if things will work. */
1051 nblank = w - (nsign + nzero + digits);
1053 if (nblank < 0)
1055 star_fill (p, w);
1056 goto done;
1059 memset (p, ' ', nblank);
1060 p += nblank;
1062 switch (sign)
1064 case SIGN_PLUS:
1065 *p++ = '+';
1066 break;
1067 case SIGN_MINUS:
1068 *p++ = '-';
1069 break;
1070 case SIGN_NONE:
1071 break;
1074 memset (p, '0', nzero);
1075 p += nzero;
1077 memcpy (p, q, digits);
1079 done:
1080 return;
1084 /* Convert unsigned octal to ascii. */
1086 static const char *
1087 otoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
1089 char *p;
1091 assert (len >= GFC_OTOA_BUF_SIZE);
1093 if (n == 0)
1094 return "0";
1096 p = buffer + GFC_OTOA_BUF_SIZE - 1;
1097 *p = '\0';
1099 while (n != 0)
1101 *--p = '0' + (n & 7);
1102 n >>= 3;
1105 return p;
1109 /* Convert unsigned binary to ascii. */
1111 static const char *
1112 btoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
1114 char *p;
1116 assert (len >= GFC_BTOA_BUF_SIZE);
1118 if (n == 0)
1119 return "0";
1121 p = buffer + GFC_BTOA_BUF_SIZE - 1;
1122 *p = '\0';
1124 while (n != 0)
1126 *--p = '0' + (n & 1);
1127 n >>= 1;
1130 return p;
1134 void
1135 write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1137 write_decimal (dtp, f, p, len, (void *) gfc_itoa);
1141 void
1142 write_b (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1144 write_int (dtp, f, p, len, btoa);
1148 void
1149 write_o (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1151 write_int (dtp, f, p, len, otoa);
1154 void
1155 write_z (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1157 write_int (dtp, f, p, len, xtoa);
1161 void
1162 write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1164 write_float (dtp, f, p, len);
1168 void
1169 write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1171 write_float (dtp, f, p, len);
1175 void
1176 write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1178 write_float (dtp, f, p, len);
1182 void
1183 write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1185 write_float (dtp, f, p, len);
1189 void
1190 write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
1192 write_float (dtp, f, p, len);
1196 /* Take care of the X/TR descriptor. */
1198 void
1199 write_x (st_parameter_dt *dtp, int len, int nspaces)
1201 char *p;
1203 p = write_block (dtp, len);
1204 if (p == NULL)
1205 return;
1207 if (nspaces > 0)
1208 memset (&p[len - nspaces], ' ', nspaces);
1212 /* List-directed writing. */
1215 /* Write a single character to the output. Returns nonzero if
1216 something goes wrong. */
1218 static int
1219 write_char (st_parameter_dt *dtp, char c)
1221 char *p;
1223 p = write_block (dtp, 1);
1224 if (p == NULL)
1225 return 1;
1227 *p = c;
1229 return 0;
1233 /* Write a list-directed logical value. */
1235 static void
1236 write_logical (st_parameter_dt *dtp, const char *source, int length)
1238 write_char (dtp, extract_int (source, length) ? 'T' : 'F');
1242 /* Write a list-directed integer value. */
1244 static void
1245 write_integer (st_parameter_dt *dtp, const char *source, int length)
1247 char *p;
1248 const char *q;
1249 int digits;
1250 int width;
1251 char itoa_buf[GFC_ITOA_BUF_SIZE];
1253 q = gfc_itoa (extract_int (source, length), itoa_buf, sizeof (itoa_buf));
1255 switch (length)
1257 case 1:
1258 width = 4;
1259 break;
1261 case 2:
1262 width = 6;
1263 break;
1265 case 4:
1266 width = 11;
1267 break;
1269 case 8:
1270 width = 20;
1271 break;
1273 default:
1274 width = 0;
1275 break;
1278 digits = strlen (q);
1280 if (width < digits)
1281 width = digits;
1282 p = write_block (dtp, width);
1283 if (p == NULL)
1284 return;
1285 if (dtp->u.p.no_leading_blank)
1287 memcpy (p, q, digits);
1288 memset (p + digits, ' ', width - digits);
1290 else
1292 memset (p, ' ', width - digits);
1293 memcpy (p + width - digits, q, digits);
1298 /* Write a list-directed string. We have to worry about delimiting
1299 the strings if the file has been opened in that mode. */
1301 static void
1302 write_character (st_parameter_dt *dtp, const char *source, int length)
1304 int i, extra;
1305 char *p, d;
1307 switch (dtp->u.p.current_unit->flags.delim)
1309 case DELIM_APOSTROPHE:
1310 d = '\'';
1311 break;
1312 case DELIM_QUOTE:
1313 d = '"';
1314 break;
1315 default:
1316 d = ' ';
1317 break;
1320 if (d == ' ')
1321 extra = 0;
1322 else
1324 extra = 2;
1326 for (i = 0; i < length; i++)
1327 if (source[i] == d)
1328 extra++;
1331 p = write_block (dtp, length + extra);
1332 if (p == NULL)
1333 return;
1335 if (d == ' ')
1336 memcpy (p, source, length);
1337 else
1339 *p++ = d;
1341 for (i = 0; i < length; i++)
1343 *p++ = source[i];
1344 if (source[i] == d)
1345 *p++ = d;
1348 *p = d;
1353 /* Output a real number with default format.
1354 This is 1PG14.7E2 for REAL(4), 1PG23.15E3 for REAL(8),
1355 1PG24.15E4 for REAL(10) and 1PG40.31E4 for REAL(16). */
1357 static void
1358 write_real (st_parameter_dt *dtp, const char *source, int length)
1360 fnode f ;
1361 int org_scale = dtp->u.p.scale_factor;
1362 f.format = FMT_G;
1363 dtp->u.p.scale_factor = 1;
1364 switch (length)
1366 case 4:
1367 f.u.real.w = 14;
1368 f.u.real.d = 7;
1369 f.u.real.e = 2;
1370 break;
1371 case 8:
1372 f.u.real.w = 23;
1373 f.u.real.d = 15;
1374 f.u.real.e = 3;
1375 break;
1376 case 10:
1377 f.u.real.w = 28;
1378 f.u.real.d = 19;
1379 f.u.real.e = 4;
1380 break;
1381 case 16:
1382 f.u.real.w = 40;
1383 f.u.real.d = 31;
1384 f.u.real.e = 4;
1385 break;
1386 default:
1387 internal_error (&dtp->common, "bad real kind");
1388 break;
1390 write_float (dtp, &f, source , length);
1391 dtp->u.p.scale_factor = org_scale;
1395 static void
1396 write_complex (st_parameter_dt *dtp, const char *source, int kind, size_t size)
1398 if (write_char (dtp, '('))
1399 return;
1400 write_real (dtp, source, kind);
1402 if (write_char (dtp, ','))
1403 return;
1404 write_real (dtp, source + size / 2, kind);
1406 write_char (dtp, ')');
1410 /* Write the separator between items. */
1412 static void
1413 write_separator (st_parameter_dt *dtp)
1415 char *p;
1417 p = write_block (dtp, options.separator_len);
1418 if (p == NULL)
1419 return;
1421 memcpy (p, options.separator, options.separator_len);
1425 /* Write an item with list formatting.
1426 TODO: handle skipping to the next record correctly, particularly
1427 with strings. */
1429 static void
1430 list_formatted_write_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
1431 size_t size)
1433 if (dtp->u.p.current_unit == NULL)
1434 return;
1436 if (dtp->u.p.first_item)
1438 dtp->u.p.first_item = 0;
1439 write_char (dtp, ' ');
1441 else
1443 if (type != BT_CHARACTER || !dtp->u.p.char_flag ||
1444 dtp->u.p.current_unit->flags.delim != DELIM_NONE)
1445 write_separator (dtp);
1448 switch (type)
1450 case BT_INTEGER:
1451 write_integer (dtp, p, kind);
1452 break;
1453 case BT_LOGICAL:
1454 write_logical (dtp, p, kind);
1455 break;
1456 case BT_CHARACTER:
1457 write_character (dtp, p, kind);
1458 break;
1459 case BT_REAL:
1460 write_real (dtp, p, kind);
1461 break;
1462 case BT_COMPLEX:
1463 write_complex (dtp, p, kind, size);
1464 break;
1465 default:
1466 internal_error (&dtp->common, "list_formatted_write(): Bad type");
1469 dtp->u.p.char_flag = (type == BT_CHARACTER);
1473 void
1474 list_formatted_write (st_parameter_dt *dtp, bt type, void *p, int kind,
1475 size_t size, size_t nelems)
1477 size_t elem;
1478 char *tmp;
1480 tmp = (char *) p;
1482 /* Big loop over all the elements. */
1483 for (elem = 0; elem < nelems; elem++)
1485 dtp->u.p.item_count++;
1486 list_formatted_write_scalar (dtp, type, tmp + size*elem, kind, size);
1490 /* NAMELIST OUTPUT
1492 nml_write_obj writes a namelist object to the output stream. It is called
1493 recursively for derived type components:
1494 obj = is the namelist_info for the current object.
1495 offset = the offset relative to the address held by the object for
1496 derived type arrays.
1497 base = is the namelist_info of the derived type, when obj is a
1498 component.
1499 base_name = the full name for a derived type, including qualifiers
1500 if any.
1501 The returned value is a pointer to the object beyond the last one
1502 accessed, including nested derived types. Notice that the namelist is
1503 a linear linked list of objects, including derived types and their
1504 components. A tree, of sorts, is implied by the compound names of
1505 the derived type components and this is how this function recurses through
1506 the list. */
1508 /* A generous estimate of the number of characters needed to print
1509 repeat counts and indices, including commas, asterices and brackets. */
1511 #define NML_DIGITS 20
1513 static namelist_info *
1514 nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
1515 namelist_info * base, char * base_name)
1517 int rep_ctr;
1518 int num;
1519 int nml_carry;
1520 index_type len;
1521 index_type obj_size;
1522 index_type nelem;
1523 index_type dim_i;
1524 index_type clen;
1525 index_type elem_ctr;
1526 index_type obj_name_len;
1527 void * p ;
1528 char cup;
1529 char * obj_name;
1530 char * ext_name;
1531 char rep_buff[NML_DIGITS];
1532 namelist_info * cmp;
1533 namelist_info * retval = obj->next;
1535 /* Write namelist variable names in upper case. If a derived type,
1536 nothing is output. If a component, base and base_name are set. */
1538 if (obj->type != GFC_DTYPE_DERIVED)
1540 #ifdef HAVE_CRLF
1541 write_character (dtp, "\r\n ", 3);
1542 #else
1543 write_character (dtp, "\n ", 2);
1544 #endif
1545 len = 0;
1546 if (base)
1548 len =strlen (base->var_name);
1549 for (dim_i = 0; dim_i < (index_type) strlen (base_name); dim_i++)
1551 cup = toupper (base_name[dim_i]);
1552 write_character (dtp, &cup, 1);
1555 for (dim_i =len; dim_i < (index_type) strlen (obj->var_name); dim_i++)
1557 cup = toupper (obj->var_name[dim_i]);
1558 write_character (dtp, &cup, 1);
1560 write_character (dtp, "=", 1);
1563 /* Counts the number of data output on a line, including names. */
1565 num = 1;
1567 len = obj->len;
1569 switch (obj->type)
1572 case GFC_DTYPE_REAL:
1573 obj_size = size_from_real_kind (len);
1574 break;
1576 case GFC_DTYPE_COMPLEX:
1577 obj_size = size_from_complex_kind (len);
1578 break;
1580 case GFC_DTYPE_CHARACTER:
1581 obj_size = obj->string_length;
1582 break;
1584 default:
1585 obj_size = len;
1588 if (obj->var_rank)
1589 obj_size = obj->size;
1591 /* Set the index vector and count the number of elements. */
1593 nelem = 1;
1594 for (dim_i=0; dim_i < obj->var_rank; dim_i++)
1596 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1597 nelem = nelem * (obj->dim[dim_i].ubound + 1 - obj->dim[dim_i].lbound);
1600 /* Main loop to output the data held in the object. */
1602 rep_ctr = 1;
1603 for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
1606 /* Build the pointer to the data value. The offset is passed by
1607 recursive calls to this function for arrays of derived types.
1608 Is NULL otherwise. */
1610 p = (void *)(obj->mem_pos + elem_ctr * obj_size);
1611 p += offset;
1613 /* Check for repeat counts of intrinsic types. */
1615 if ((elem_ctr < (nelem - 1)) &&
1616 (obj->type != GFC_DTYPE_DERIVED) &&
1617 !memcmp (p, (void*)(p + obj_size ), obj_size ))
1619 rep_ctr++;
1622 /* Execute a repeated output. Note the flag no_leading_blank that
1623 is used in the functions used to output the intrinsic types. */
1625 else
1627 if (rep_ctr > 1)
1629 st_sprintf(rep_buff, " %d*", rep_ctr);
1630 write_character (dtp, rep_buff, strlen (rep_buff));
1631 dtp->u.p.no_leading_blank = 1;
1633 num++;
1635 /* Output the data, if an intrinsic type, or recurse into this
1636 routine to treat derived types. */
1638 switch (obj->type)
1641 case GFC_DTYPE_INTEGER:
1642 write_integer (dtp, p, len);
1643 break;
1645 case GFC_DTYPE_LOGICAL:
1646 write_logical (dtp, p, len);
1647 break;
1649 case GFC_DTYPE_CHARACTER:
1650 if (dtp->u.p.nml_delim)
1651 write_character (dtp, &dtp->u.p.nml_delim, 1);
1652 write_character (dtp, p, obj->string_length);
1653 if (dtp->u.p.nml_delim)
1654 write_character (dtp, &dtp->u.p.nml_delim, 1);
1655 break;
1657 case GFC_DTYPE_REAL:
1658 write_real (dtp, p, len);
1659 break;
1661 case GFC_DTYPE_COMPLEX:
1662 dtp->u.p.no_leading_blank = 0;
1663 num++;
1664 write_complex (dtp, p, len, obj_size);
1665 break;
1667 case GFC_DTYPE_DERIVED:
1669 /* To treat a derived type, we need to build two strings:
1670 ext_name = the name, including qualifiers that prepends
1671 component names in the output - passed to
1672 nml_write_obj.
1673 obj_name = the derived type name with no qualifiers but %
1674 appended. This is used to identify the
1675 components. */
1677 /* First ext_name => get length of all possible components */
1679 ext_name = (char*)get_mem ( (base_name ? strlen (base_name) : 0)
1680 + (base ? strlen (base->var_name) : 0)
1681 + strlen (obj->var_name)
1682 + obj->var_rank * NML_DIGITS
1683 + 1);
1685 strcpy(ext_name, base_name ? base_name : "");
1686 clen = base ? strlen (base->var_name) : 0;
1687 strcat (ext_name, obj->var_name + clen);
1689 /* Append the qualifier. */
1691 for (dim_i = 0; dim_i < obj->var_rank; dim_i++)
1693 strcat (ext_name, dim_i ? "" : "(");
1694 clen = strlen (ext_name);
1695 st_sprintf (ext_name + clen, "%d", (int) obj->ls[dim_i].idx);
1696 strcat (ext_name, (dim_i == obj->var_rank - 1) ? ")" : ",");
1699 /* Now obj_name. */
1701 obj_name_len = strlen (obj->var_name) + 1;
1702 obj_name = get_mem (obj_name_len+1);
1703 strcpy (obj_name, obj->var_name);
1704 strcat (obj_name, "%");
1706 /* Now loop over the components. Update the component pointer
1707 with the return value from nml_write_obj => this loop jumps
1708 past nested derived types. */
1710 for (cmp = obj->next;
1711 cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
1712 cmp = retval)
1714 retval = nml_write_obj (dtp, cmp,
1715 (index_type)(p - obj->mem_pos),
1716 obj, ext_name);
1719 free_mem (obj_name);
1720 free_mem (ext_name);
1721 goto obj_loop;
1723 default:
1724 internal_error (&dtp->common, "Bad type for namelist write");
1727 /* Reset the leading blank suppression, write a comma and, if 5
1728 values have been output, write a newline and advance to column
1729 2. Reset the repeat counter. */
1731 dtp->u.p.no_leading_blank = 0;
1732 write_character (dtp, ",", 1);
1733 if (num > 5)
1735 num = 0;
1736 #ifdef HAVE_CRLF
1737 write_character (dtp, "\r\n ", 3);
1738 #else
1739 write_character (dtp, "\n ", 2);
1740 #endif
1742 rep_ctr = 1;
1745 /* Cycle through and increment the index vector. */
1747 obj_loop:
1749 nml_carry = 1;
1750 for (dim_i = 0; nml_carry && (dim_i < obj->var_rank); dim_i++)
1752 obj->ls[dim_i].idx += nml_carry ;
1753 nml_carry = 0;
1754 if (obj->ls[dim_i].idx > (ssize_t)obj->dim[dim_i].ubound)
1756 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1757 nml_carry = 1;
1762 /* Return a pointer beyond the furthest object accessed. */
1764 return retval;
1767 /* This is the entry function for namelist writes. It outputs the name
1768 of the namelist and iterates through the namelist by calls to
1769 nml_write_obj. The call below has dummys in the arguments used in
1770 the treatment of derived types. */
1772 void
1773 namelist_write (st_parameter_dt *dtp)
1775 namelist_info * t1, *t2, *dummy = NULL;
1776 index_type i;
1777 index_type dummy_offset = 0;
1778 char c;
1779 char * dummy_name = NULL;
1780 unit_delim tmp_delim;
1782 /* Set the delimiter for namelist output. */
1784 tmp_delim = dtp->u.p.current_unit->flags.delim;
1785 dtp->u.p.current_unit->flags.delim = DELIM_NONE;
1786 switch (tmp_delim)
1788 case (DELIM_QUOTE):
1789 dtp->u.p.nml_delim = '"';
1790 break;
1792 case (DELIM_APOSTROPHE):
1793 dtp->u.p.nml_delim = '\'';
1794 break;
1796 default:
1797 dtp->u.p.nml_delim = '\0';
1798 break;
1801 write_character (dtp, "&", 1);
1803 /* Write namelist name in upper case - f95 std. */
1805 for (i = 0 ;i < dtp->namelist_name_len ;i++ )
1807 c = toupper (dtp->namelist_name[i]);
1808 write_character (dtp, &c ,1);
1811 if (dtp->u.p.ionml != NULL)
1813 t1 = dtp->u.p.ionml;
1814 while (t1 != NULL)
1816 t2 = t1;
1817 t1 = nml_write_obj (dtp, t2, dummy_offset, dummy, dummy_name);
1820 #ifdef HAVE_CRLF
1821 write_character (dtp, " /\r\n", 5);
1822 #else
1823 write_character (dtp, " /\n", 4);
1824 #endif
1826 /* Recover the original delimiter. */
1828 dtp->u.p.current_unit->flags.delim = tmp_delim;
1831 #undef NML_DIGITS