1 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
4 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6 Libgfortran is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 Libgfortran is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Libgfortran; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
24 #include "libgfortran.h"
29 #define star_fill(p, n) memset(p, '*', n)
33 { SIGN_NONE, SIGN_MINUS, SIGN_PLUS }
38 write_a (fnode * f, const char *source, int len)
43 wlen = f->u.string.length < 0 ? len : f->u.string.length;
45 p = write_block (wlen);
50 memcpy (p, source, wlen);
53 memset (p, ' ', wlen - len);
54 memcpy (p + wlen - len, source, len);
59 extract_int (const void *p, int len)
69 i = *((const int8_t *) p);
72 i = *((const int16_t *) p);
75 i = *((const int32_t *) p);
78 i = *((const int64_t *) p);
81 internal_error ("bad integer kind");
88 extract_real (const void *p, int len)
94 i = *((const float *) p);
97 i = *((const double *) p);
100 internal_error ("bad real kind");
107 /* Given a flag that indicate if a value is negative or not, return a
108 sign_t that gives the sign that we need to produce. */
111 calculate_sign (int negative_flag)
113 sign_t s = SIGN_NONE;
118 switch (g.sign_status)
127 s = options.optional_plus ? SIGN_PLUS : SIGN_NONE;
135 /* Returns the value of 10**d. */
138 calculate_exp (int d)
143 for (i = 0; i< (d >= 0 ? d : -d); i++)
146 r = (d >= 0) ? r : 1.0 / r;
152 /* Generate corresponding I/O format for FMT_G output.
153 The rules to translate FMT_G to FMT_E or FNT_F from DEC fortran
154 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
156 Data Magnitude Equivalent Conversion
157 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
158 m = 0 F(w-n).(d-1), n' '
159 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
160 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
161 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
162 ................ ..........
163 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
164 m >= 10**d-0.5 Ew.d[Ee]
166 notes: for Gw.d , n' ' means 4 blanks
167 for Gw.dEe, n' ' means e+2 blanks */
170 calculate_G_format (fnode *f, double value, int len, int *num_blank)
180 newf = get_mem (sizeof (fnode));
182 /* Absolute value. */
183 m = (value > 0.0) ? value : -value;
185 /* In case of the two data magnitude ranges,
186 generate E editing, Ew.d[Ee]. */
187 exp_d = calculate_exp (d);
188 if ((m > 0.0 && m < 0.1 - 0.05 / (double) exp_d)
189 || (m >= (double) exp_d - 0.5 ))
191 newf->format = FMT_E;
199 /* Use binary search to find the data magnitude range. */
209 mid = (low + high) / 2;
211 /* 0.1 * 10**mid - 0.5 * 10**(mid-d-1) */
212 temp = 0.1 * calculate_exp (mid) - 0.5 * calculate_exp (mid - d - 1);
217 if (ubound == lbound + 1)
224 if (ubound == lbound + 1)
235 /* Generate the F editing. F(w-4).(-(mid-d-1)), 4' '. */
236 newf->format = FMT_F;
237 newf->u.real.w = f->u.real.w - 4;
241 newf->u.real.d = d - 1;
243 newf->u.real.d = - (mid - d - 1);
247 /* For F editing, the scale factor is ignored. */
253 /* Output a real number according to its format which is FMT_G free. */
256 output_float (fnode *f, double value, int len)
260 int nsign, nblank, nesign;
261 int sca, neval, itmp;
263 const char *q, *intstr, *base;
269 double minv = 0.0, maxv = 0.0;
270 sign_t sign = SIGN_NONE, esign = SIGN_NONE;
272 int intval = 0, intlen = 0;
275 /* EXP value for this number. */
278 /* Width of EXP and it's sign. */
285 /* Width of the EXP. */
288 sca = g.scale_factor;
291 sign = calculate_sign (n < 0.0);
295 /* Width of the sign for the whole number. */
296 nsign = (sign == SIGN_NONE ? 0 : 1);
303 if (ft == FMT_F || ft == FMT_E || ft == FMT_D)
312 /* Calculate the new val of the number with consideration
313 of global scale value. */
323 /* Now calculate the new Exp value for this number. */
324 sca = g.scale_factor;
343 /* OK, let's scale the number to appropriate range. */
344 while (scale_flag && n > 0.0 && n < minv)
352 while (scale_flag && n > 0.0 && n > maxv)
361 /* It is time to process the EXP part of the number.
362 Value of 'nesign' is 0 unless following codes is executed. */
365 /* Sign of the EXP value. */
374 /* Width of the EXP. */
385 /* Got the width of EXP. */
389 /* Minimum value of the width would be 2. */
393 nesign = 1 ; /* We must give a position for the 'exp_char' */
395 nesign = e + nesign + (esign != SIGN_NONE ? 1 : 0);
400 intstr = itoa (intval);
401 intlen = strlen (intstr);
403 q = rtoa (n, len, d);
406 /* Select a width if none was specified. */
416 nblank = w - (nsign + intlen + d + nesign);
417 if (nblank == -1 && ft != FMT_F)
421 nblank = w - (nsign + intlen + d + nesign);
423 /* Don't let a leading '0' cause field overflow. */
424 if (nblank == -1 && ft == FMT_F && q[0] == '0')
435 memset (p, ' ', nblank);
450 memcpy (p, q, intlen + d + 1);
471 for (itmp = 0; itmp < e - digits; itmp++)
473 memcpy (p, q, digits);
482 write_l (fnode * f, char *source, int len)
487 p = write_block (f->u.w);
491 memset (p, ' ', f->u.w - 1);
492 n = extract_int (source, len);
493 p[f->u.w - 1] = (n) ? 'T' : 'F';
496 /* Output a real number according to its format. */
499 write_float (fnode *f, const char *source, int len)
506 n = extract_real (source, len);
508 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
514 p = write_block (nb);
531 memcpy(p + nb - 8, "Infinity", 8);
533 memcpy(p + nb - 3, "Inf", 3);
534 if (nb < 8 && nb > 3)
540 memcpy(p + nb - 3, "NaN", 3);
545 if (f->format != FMT_G)
547 output_float (f, n, len);
551 f2 = calculate_G_format(f, n, len, &nb);
552 output_float (f2, n, len);
558 p = write_block (nb);
566 write_int (fnode *f, const char *source, int len, char *(*conv) (uint64_t))
570 int w, m, digits, nzero, nblank;
576 n = extract_int (source, len);
580 if (m == 0 && n == 0)
604 /* Select a width if none was specified. The idea here is to always
608 w = ((digits < m) ? m : digits);
618 /* See if things will work. */
620 nblank = w - (nzero + digits);
628 memset (p, ' ', nblank);
631 memset (p, '0', nzero);
634 memcpy (p, q, digits);
641 write_decimal (fnode *f, const char *source, int len, char *(*conv) (int64_t))
644 int w, m, digits, nsign, nzero, nblank;
651 n = extract_int (source, len);
655 if (m == 0 && n == 0)
668 sign = calculate_sign (n < 0);
672 nsign = sign == SIGN_NONE ? 0 : 1;
677 /* Select a width if none was specified. The idea here is to always
681 w = ((digits < m) ? m : digits) + nsign;
691 /* See if things will work. */
693 nblank = w - (nsign + nzero + digits);
701 memset (p, ' ', nblank);
716 memset (p, '0', nzero);
719 memcpy (p, q, digits);
726 /* Convert unsigned octal to ascii. */
740 p = scratch + sizeof (SCRATCH_SIZE) - 1;
754 /* Convert unsigned binary to ascii. */
768 p = scratch + sizeof (SCRATCH_SIZE) - 1;
773 *p-- = '0' + (n & 1);
782 write_i (fnode * f, const char *p, int len)
785 write_decimal (f, p, len, (void *) itoa);
790 write_b (fnode * f, const char *p, int len)
793 write_int (f, p, len, btoa);
798 write_o (fnode * f, const char *p, int len)
801 write_int (f, p, len, otoa);
805 write_z (fnode * f, const char *p, int len)
808 write_int (f, p, len, xtoa);
813 write_d (fnode *f, const char *p, int len)
816 write_float (f, p, len);
821 write_e (fnode *f, const char *p, int len)
824 write_float (f, p, len);
829 write_f (fnode *f, const char *p, int len)
832 write_float (f, p, len);
837 write_en (fnode *f, const char *p, int len)
840 write_float (f, p, len);
845 write_es (fnode *f, const char *p, int len)
848 write_float (f, p, len);
852 /* Take care of the X/TR descriptor. */
859 p = write_block (f->u.n);
863 memset (p, ' ', f->u.n);
867 /* List-directed writing. */
870 /* Write a single character to the output. Returns nonzero if
871 something goes wrong. */
888 /* Write a list-directed logical value. */
891 write_logical (const char *source, int length)
893 write_char (extract_int (source, length) ? 'T' : 'F');
897 /* Write a list-directed integer value. */
900 write_integer (const char *source, int length)
907 q = itoa (extract_int (source, length));
936 p = write_block (width) ;
938 memset(p ,' ', width - digits) ;
939 memcpy (p + width - digits, q, digits);
943 /* Write a list-directed string. We have to worry about delimiting
944 the strings if the file has been opened in that mode. */
947 write_character (const char *source, int length)
952 switch (current_unit->flags.delim)
954 case DELIM_APOSTROPHE:
971 for (i = 0; i < length; i++)
976 p = write_block (length + extra);
981 memcpy (p, source, length);
986 for (i = 0; i < length; i++)
998 /* Output a real number with default format.
999 This is 1PG14.7E2 for REAL(4) and 1PG23.15E3 for REAL(8). */
1002 write_real (const char *source, int length)
1005 int org_scale = g.scale_factor;
1020 write_float (&f, source , length);
1021 g.scale_factor = org_scale;
1026 write_complex (const char *source, int len)
1029 if (write_char ('('))
1031 write_real (source, len);
1033 if (write_char (','))
1035 write_real (source + len, len);
1041 /* Write the separator between items. */
1044 write_separator (void)
1048 p = write_block (options.separator_len);
1052 memcpy (p, options.separator, options.separator_len);
1056 /* Write an item with list formatting.
1057 TODO: handle skipping to the next record correctly, particularly
1061 list_formatted_write (bt type, void *p, int len)
1063 static int char_flag;
1065 if (current_unit == NULL)
1076 if (type != BT_CHARACTER || !char_flag ||
1077 current_unit->flags.delim != DELIM_NONE)
1084 write_integer (p, len);
1087 write_logical (p, len);
1090 write_character (p, len);
1093 write_real (p, len);
1096 write_complex (p, len);
1099 internal_error ("list_formatted_write(): Bad type");
1102 char_flag = (type == BT_CHARACTER);
1106 namelist_write (void)
1108 namelist_info * t1, *t2;
1113 write_character("&",1);
1114 write_character (ioparm.namelist_name, ioparm.namelist_name_len);
1115 write_character("\n",1);
1127 write_character(t2->var_name, strlen(t2->var_name));
1128 write_character("=",1);
1135 write_integer (p, len);
1138 write_logical (p, len);
1141 write_character (p, t2->string_length);
1144 write_real (p, len);
1147 write_complex (p, len);
1150 internal_error ("Bad type for namelist write");
1152 write_character(",",1);
1156 write_character("\n",1);
1160 write_character("/",1);