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)
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
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, 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA. */
37 #include "libgfortran.h"
41 #define star_fill(p, n) memset(p, '*', n)
45 { SIGN_NONE, SIGN_MINUS, SIGN_PLUS }
49 static int no_leading_blank = 0 ;
52 write_a (fnode * f, const char *source, int len)
57 wlen = f->u.string.length < 0 ? len : f->u.string.length;
59 p = write_block (wlen);
64 memcpy (p, source, wlen);
67 memset (p, ' ', wlen - len);
68 memcpy (p + wlen - len, source, len);
73 extract_int (const void *p, int len)
83 i = *((const int8_t *) p);
86 i = *((const int16_t *) p);
89 i = *((const int32_t *) p);
92 i = *((const int64_t *) p);
95 internal_error ("bad integer kind");
102 extract_real (const void *p, int len)
108 i = *((const float *) p);
111 i = *((const double *) p);
114 internal_error ("bad real kind");
121 /* Given a flag that indicate if a value is negative or not, return a
122 sign_t that gives the sign that we need to produce. */
125 calculate_sign (int negative_flag)
127 sign_t s = SIGN_NONE;
132 switch (g.sign_status)
141 s = options.optional_plus ? SIGN_PLUS : SIGN_NONE;
149 /* Returns the value of 10**d. */
152 calculate_exp (int d)
157 for (i = 0; i< (d >= 0 ? d : -d); i++)
160 r = (d >= 0) ? r : 1.0 / r;
166 /* Generate corresponding I/O format for FMT_G output.
167 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
168 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
170 Data Magnitude Equivalent Conversion
171 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
172 m = 0 F(w-n).(d-1), n' '
173 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
174 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
175 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
176 ................ ..........
177 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
178 m >= 10**d-0.5 Ew.d[Ee]
180 notes: for Gw.d , n' ' means 4 blanks
181 for Gw.dEe, n' ' means e+2 blanks */
184 calculate_G_format (fnode *f, double value, int *num_blank)
194 newf = get_mem (sizeof (fnode));
196 /* Absolute value. */
197 m = (value > 0.0) ? value : -value;
199 /* In case of the two data magnitude ranges,
200 generate E editing, Ew.d[Ee]. */
201 exp_d = calculate_exp (d);
202 if ((m > 0.0 && m < 0.1 - 0.05 / (double) exp_d)
203 || (m >= (double) exp_d - 0.5 ))
205 newf->format = FMT_E;
213 /* Use binary search to find the data magnitude range. */
223 mid = (low + high) / 2;
225 /* 0.1 * 10**mid - 0.5 * 10**(mid-d-1) */
226 temp = 0.1 * calculate_exp (mid) - 0.5 * calculate_exp (mid - d - 1);
231 if (ubound == lbound + 1)
238 if (ubound == lbound + 1)
249 /* Pad with blanks where the exponent would be. */
255 /* Generate the F editing. F(w-n).(-(mid-d-1)), n' '. */
256 newf->format = FMT_F;
257 newf->u.real.w = f->u.real.w - *num_blank;
261 newf->u.real.d = d - 1;
263 newf->u.real.d = - (mid - d - 1);
265 /* For F editing, the scale factor is ignored. */
271 /* Output a real number according to its format which is FMT_G free. */
274 output_float (fnode *f, double value)
276 /* This must be large enough to accurately hold any value. */
287 /* Number of digits before the decimal point. */
289 /* Number of zeros after the decimal point. */
291 /* Number of digits after the decimal point. */
293 /* Number of zeros after the decimal point, whatever the precision. */
308 /* We should always know the field width and precision. */
310 internal_error ("Unspecified precision");
312 /* Use sprintf to print the number in the format +D.DDDDe+ddd
313 For an N digit exponent, this gives us (32-6)-N digits after the
314 decimal point, plus another one before the decimal point. */
315 sign = calculate_sign (value < 0.0);
319 /* Printf always prints at least two exponent digits. */
324 abslog = fabs(log10 (value));
328 edigits = 1 + (int) log10 (abslog);
331 if (ft == FMT_F || ft == FMT_EN
332 || ((ft == FMT_D || ft == FMT_E) && g.scale_factor != 0))
334 /* Always convert at full precision to avoid double rounding. */
335 ndigits = 27 - edigits;
339 /* We know the number of digits, so can let printf do the rounding
345 if (ndigits > 27 - edigits)
346 ndigits = 27 - edigits;
349 sprintf (buffer, "%+-#31.*e", ndigits - 1, value);
351 /* Check the resulting string has punctuation in the correct places. */
352 if (buffer[2] != '.' || buffer[ndigits + 2] != 'e')
353 internal_error ("printf is broken");
355 /* Read the exponent back in. */
356 e = atoi (&buffer[ndigits + 3]) + 1;
358 /* Make sure zero comes out as 0.0e0. */
362 /* Normalize the fractional component. */
363 buffer[2] = buffer[1];
366 /* Figure out where to place the decimal point. */
370 nbefore = e + g.scale_factor;
403 nafter = (d - i) + 1;
419 /* The exponent must be a multiple of three, with 1-3 digits before
420 the decimal point. */
429 nbefore = 3 - nbefore;
448 /* Should never happen. */
449 internal_error ("Unexpected format token");
452 /* Round the value. */
453 if (nbefore + nafter == 0)
456 if (nzero_real == d && digits[0] >= '5')
458 /* We rounded to zero but shouldn't have */
465 else if (nbefore + nafter < ndigits)
467 ndigits = nbefore + nafter;
469 if (digits[i] >= '5')
471 /* Propagate the carry. */
472 for (i--; i >= 0; i--)
474 if (digits[i] != '9')
484 /* The carry overflowed. Fortunately we have some spare space
485 at the start of the buffer. We may discard some digits, but
486 this is ok because we already know they are zero. */
499 else if (ft == FMT_EN)
514 /* Calculate the format of the exponent field. */
518 for (i = abs (e); i >= 10; i /= 10)
523 /* Width not specified. Must be no more than 3 digits. */
524 if (e > 999 || e < -999)
529 if (e > 99 || e < -99)
535 /* Exponent width specified, check it is wide enough. */
536 if (edigits > f->u.real.e)
539 edigits = f->u.real.e + 2;
545 /* Pick a field size if none was specified. */
547 w = nbefore + nzero + nafter + (sign != SIGN_NONE ? 2 : 1);
549 /* Create the ouput buffer. */
550 out = write_block (w);
554 /* Zero values always output as positive, even if the value was negative
556 for (i = 0; i < ndigits; i++)
558 if (digits[i] != '0')
562 sign = calculate_sign (0);
564 /* Work out how much padding is needed. */
565 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
566 if (sign != SIGN_NONE)
569 /* Check the value fits in the specified field width. */
570 if (nblanks < 0 || edigits == -1)
576 /* See if we have space for a zero before the decimal point. */
577 if (nbefore == 0 && nblanks > 0)
585 /* Padd to full field width. */
588 if ( ( nblanks > 0 ) && !no_leading_blank )
590 memset (out, ' ', nblanks);
594 /* Output the initial sign (if any). */
595 if (sign == SIGN_PLUS)
597 else if (sign == SIGN_MINUS)
600 /* Output an optional leading zero. */
604 /* Output the part before the decimal point, padding with zeros. */
607 if (nbefore > ndigits)
612 memcpy (out, digits, i);
620 /* Output the decimal point. */
623 /* Output leading zeros after the decimal point. */
626 for (i = 0; i < nzero; i++)
630 /* Output digits after the decimal point, padding with zeros. */
633 if (nafter > ndigits)
638 memcpy (out, digits, i);
647 /* Output the exponent. */
656 snprintf (buffer, 32, "%+0*d", edigits, e);
658 sprintf (buffer, "%+0*d", edigits, e);
660 memcpy (out, buffer, edigits);
663 if ( no_leading_blank )
666 memset( out , ' ' , nblanks );
667 no_leading_blank = 0;
673 write_l (fnode * f, char *source, int len)
678 p = write_block (f->u.w);
682 memset (p, ' ', f->u.w - 1);
683 n = extract_int (source, len);
684 p[f->u.w - 1] = (n) ? 'T' : 'F';
687 /* Output a real number according to its format. */
690 write_float (fnode *f, const char *source, int len)
693 int nb =0, res, save_scale_factor;
697 n = extract_real (source, len);
699 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
705 p = write_block (nb);
722 memcpy(p + nb - 8, "Infinity", 8);
724 memcpy(p + nb - 3, "Inf", 3);
725 if (nb < 8 && nb > 3)
731 memcpy(p + nb - 3, "NaN", 3);
736 if (f->format != FMT_G)
742 save_scale_factor = g.scale_factor;
743 f2 = calculate_G_format(f, n, &nb);
744 output_float (f2, n);
745 g.scale_factor = save_scale_factor;
751 p = write_block (nb);
759 write_int (fnode *f, const char *source, int len, char *(*conv) (uint64_t))
763 int w, m, digits, nzero, nblank;
769 n = extract_int (source, len);
773 if (m == 0 && n == 0)
797 /* Select a width if none was specified. The idea here is to always
801 w = ((digits < m) ? m : digits);
811 /* See if things will work. */
813 nblank = w - (nzero + digits);
822 if (!no_leading_blank)
824 memset (p, ' ', nblank);
826 memset (p, '0', nzero);
828 memcpy (p, q, digits);
832 memset (p, '0', nzero);
834 memcpy (p, q, digits);
836 memset (p, ' ', nblank);
837 no_leading_blank = 0;
845 write_decimal (fnode *f, const char *source, int len, char *(*conv) (int64_t))
848 int w, m, digits, nsign, nzero, nblank;
855 n = extract_int (source, len);
859 if (m == 0 && n == 0)
872 sign = calculate_sign (n < 0);
876 nsign = sign == SIGN_NONE ? 0 : 1;
881 /* Select a width if none was specified. The idea here is to always
885 w = ((digits < m) ? m : digits) + nsign;
895 /* See if things will work. */
897 nblank = w - (nsign + nzero + digits);
905 memset (p, ' ', nblank);
920 memset (p, '0', nzero);
923 memcpy (p, q, digits);
930 /* Convert unsigned octal to ascii. */
944 p = scratch + sizeof (SCRATCH_SIZE) - 1;
958 /* Convert unsigned binary to ascii. */
972 p = scratch + sizeof (SCRATCH_SIZE) - 1;
977 *p-- = '0' + (n & 1);
986 write_i (fnode * f, const char *p, int len)
988 write_decimal (f, p, len, (void *) gfc_itoa);
993 write_b (fnode * f, const char *p, int len)
995 write_int (f, p, len, btoa);
1000 write_o (fnode * f, const char *p, int len)
1002 write_int (f, p, len, otoa);
1006 write_z (fnode * f, const char *p, int len)
1008 write_int (f, p, len, xtoa);
1013 write_d (fnode *f, const char *p, int len)
1015 write_float (f, p, len);
1020 write_e (fnode *f, const char *p, int len)
1022 write_float (f, p, len);
1027 write_f (fnode *f, const char *p, int len)
1029 write_float (f, p, len);
1034 write_en (fnode *f, const char *p, int len)
1036 write_float (f, p, len);
1041 write_es (fnode *f, const char *p, int len)
1043 write_float (f, p, len);
1047 /* Take care of the X/TR descriptor. */
1054 p = write_block (f->u.n);
1058 memset (p, ' ', f->u.n);
1062 /* List-directed writing. */
1065 /* Write a single character to the output. Returns nonzero if
1066 something goes wrong. */
1073 p = write_block (1);
1083 /* Write a list-directed logical value. */
1086 write_logical (const char *source, int length)
1088 write_char (extract_int (source, length) ? 'T' : 'F');
1092 /* Write a list-directed integer value. */
1095 write_integer (const char *source, int length)
1102 q = gfc_itoa (extract_int (source, length));
1127 digits = strlen (q);
1131 p = write_block (width) ;
1132 if (no_leading_blank)
1134 memcpy (p, q, digits);
1135 memset(p + digits ,' ', width - digits) ;
1139 memset(p ,' ', width - digits) ;
1140 memcpy (p + width - digits, q, digits);
1145 /* Write a list-directed string. We have to worry about delimiting
1146 the strings if the file has been opened in that mode. */
1149 write_character (const char *source, int length)
1154 switch (current_unit->flags.delim)
1156 case DELIM_APOSTROPHE:
1173 for (i = 0; i < length; i++)
1178 p = write_block (length + extra);
1183 memcpy (p, source, length);
1188 for (i = 0; i < length; i++)
1200 /* Output a real number with default format.
1201 This is 1PG14.7E2 for REAL(4) and 1PG23.15E3 for REAL(8). */
1204 write_real (const char *source, int length)
1207 int org_scale = g.scale_factor;
1222 write_float (&f, source , length);
1223 g.scale_factor = org_scale;
1228 write_complex (const char *source, int len)
1230 if (write_char ('('))
1232 write_real (source, len);
1234 if (write_char (','))
1236 write_real (source + len, len);
1242 /* Write the separator between items. */
1245 write_separator (void)
1249 p = write_block (options.separator_len);
1253 memcpy (p, options.separator, options.separator_len);
1257 /* Write an item with list formatting.
1258 TODO: handle skipping to the next record correctly, particularly
1262 list_formatted_write (bt type, void *p, int len)
1264 static int char_flag;
1266 if (current_unit == NULL)
1277 if (type != BT_CHARACTER || !char_flag ||
1278 current_unit->flags.delim != DELIM_NONE)
1285 write_integer (p, len);
1288 write_logical (p, len);
1291 write_character (p, len);
1294 write_real (p, len);
1297 write_complex (p, len);
1300 internal_error ("list_formatted_write(): Bad type");
1303 char_flag = (type == BT_CHARACTER);
1308 nml_write_obj writes a namelist object to the output stream. It is called
1309 recursively for derived type components:
1310 obj = is the namelist_info for the current object.
1311 offset = the offset relative to the address held by the object for
1312 derived type arrays.
1313 base = is the namelist_info of the derived type, when obj is a
1315 base_name = the full name for a derived type, including qualifiers
1317 The returned value is a pointer to the object beyond the last one
1318 accessed, including nested derived types. Notice that the namelist is
1319 a linear linked list of objects, including derived types and their
1320 components. A tree, of sorts, is implied by the compound names of
1321 the derived type components and this is how this function recurses through
1324 /* A generous estimate of the number of characters needed to print
1325 repeat counts and indices, including commas, asterices and brackets. */
1327 #define NML_DIGITS 20
1329 /* Stores the delimiter to be used for character objects. */
1331 static const char * nml_delim;
1333 static namelist_info *
1334 nml_write_obj (namelist_info * obj, index_type offset,
1335 namelist_info * base, char * base_name)
1341 index_type obj_size;
1345 index_type elem_ctr;
1346 index_type obj_name_len;
1351 char rep_buff[NML_DIGITS];
1352 namelist_info * cmp;
1353 namelist_info * retval = obj->next;
1355 /* Write namelist variable names in upper case. If a derived type,
1356 nothing is output. If a component, base and base_name are set. */
1358 if (obj->type != GFC_DTYPE_DERIVED)
1360 write_character ("\n ", 2);
1364 len =strlen (base->var_name);
1365 for (dim_i = 0; dim_i < (index_type) strlen (base_name); dim_i++)
1367 cup = toupper (base_name[dim_i]);
1368 write_character (&cup, 1);
1371 for (dim_i =len; dim_i < (index_type) strlen (obj->var_name); dim_i++)
1373 cup = toupper (obj->var_name[dim_i]);
1374 write_character (&cup, 1);
1376 write_character ("=", 1);
1379 /* Counts the number of data output on a line, including names. */
1385 if (obj->type == GFC_DTYPE_COMPLEX)
1387 if (obj->type == GFC_DTYPE_CHARACTER)
1388 obj_size = obj->string_length;
1390 obj_size = obj->size;
1392 /* Set the index vector and count the number of elements. */
1395 for (dim_i=0; dim_i < obj->var_rank; dim_i++)
1397 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1398 nelem = nelem * (obj->dim[dim_i].ubound + 1 - obj->dim[dim_i].lbound);
1401 /* Main loop to output the data held in the object. */
1404 for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
1407 /* Build the pointer to the data value. The offset is passed by
1408 recursive calls to this function for arrays of derived types.
1409 Is NULL otherwise. */
1411 p = (void *)(obj->mem_pos + elem_ctr * obj_size);
1414 /* Check for repeat counts of intrinsic types. */
1416 if ((elem_ctr < (nelem - 1)) &&
1417 (obj->type != GFC_DTYPE_DERIVED) &&
1418 !memcmp (p, (void*)(p + obj_size ), obj_size ))
1423 /* Execute a repeated output. Note the flag no_leading_blank that
1424 is used in the functions used to output the intrinsic types. */
1430 st_sprintf(rep_buff, " %d*", rep_ctr);
1431 write_character (rep_buff, strlen (rep_buff));
1432 no_leading_blank = 1;
1436 /* Output the data, if an intrinsic type, or recurse into this
1437 routine to treat derived types. */
1442 case GFC_DTYPE_INTEGER:
1443 write_integer (p, len);
1446 case GFC_DTYPE_LOGICAL:
1447 write_logical (p, len);
1450 case GFC_DTYPE_CHARACTER:
1452 write_character (nml_delim, 1);
1453 write_character (p, obj->string_length);
1455 write_character (nml_delim, 1);
1458 case GFC_DTYPE_REAL:
1459 write_real (p, len);
1462 case GFC_DTYPE_COMPLEX:
1463 no_leading_blank = 0;
1465 write_complex (p, len);
1468 case GFC_DTYPE_DERIVED:
1470 /* To treat a derived type, we need to build two strings:
1471 ext_name = the name, including qualifiers that prepends
1472 component names in the output - passed to
1474 obj_name = the derived type name with no qualifiers but %
1475 appended. This is used to identify the
1478 /* First ext_name => get length of all possible components */
1480 ext_name = (char*)get_mem ( (base_name ? strlen (base_name) : 0)
1481 + (base ? strlen (base->var_name) : 0)
1482 + strlen (obj->var_name)
1483 + obj->var_rank * NML_DIGITS
1486 strcpy(ext_name, base_name ? base_name : "");
1487 clen = base ? strlen (base->var_name) : 0;
1488 strcat (ext_name, obj->var_name + clen);
1490 /* Append the qualifier. */
1492 for (dim_i = 0; dim_i < obj->var_rank; dim_i++)
1494 strcat (ext_name, dim_i ? "" : "(");
1495 clen = strlen (ext_name);
1496 st_sprintf (ext_name + clen, "%d", (int) obj->ls[dim_i].idx);
1497 strcat (ext_name, (dim_i == obj->var_rank - 1) ? ")" : ",");
1502 obj_name_len = strlen (obj->var_name) + 1;
1503 obj_name = get_mem (obj_name_len+1);
1504 strcpy (obj_name, obj->var_name);
1505 strcat (obj_name, "%");
1507 /* Now loop over the components. Update the component pointer
1508 with the return value from nml_write_obj => this loop jumps
1509 past nested derived types. */
1511 for (cmp = obj->next;
1512 cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
1515 retval = nml_write_obj (cmp, (index_type)(p - obj->mem_pos),
1519 free_mem (obj_name);
1520 free_mem (ext_name);
1524 internal_error ("Bad type for namelist write");
1527 /* Reset the leading blank suppression, write a comma and, if 5
1528 values have been output, write a newline and advance to column
1529 2. Reset the repeat counter. */
1531 no_leading_blank = 0;
1532 write_character (",", 1);
1536 write_character ("\n ", 2);
1541 /* Cycle through and increment the index vector. */
1546 for (dim_i = 0; nml_carry && (dim_i < obj->var_rank); dim_i++)
1548 obj->ls[dim_i].idx += nml_carry ;
1550 if (obj->ls[dim_i].idx > (ssize_t)obj->dim[dim_i].ubound)
1552 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1558 /* Return a pointer beyond the furthest object accessed. */
1563 /* This is the entry function for namelist writes. It outputs the name
1564 of the namelist and iterates through the namelist by calls to
1565 nml_write_obj. The call below has dummys in the arguments used in
1566 the treatment of derived types. */
1569 namelist_write (void)
1571 namelist_info * t1, *t2, *dummy = NULL;
1573 index_type dummy_offset = 0;
1575 char * dummy_name = NULL;
1576 unit_delim tmp_delim;
1578 /* Set the delimiter for namelist output. */
1580 tmp_delim = current_unit->flags.delim;
1581 current_unit->flags.delim = DELIM_NONE;
1588 case (DELIM_APOSTROPHE):
1596 write_character ("&",1);
1598 /* Write namelist name in upper case - f95 std. */
1600 for (i = 0 ;i < ioparm.namelist_name_len ;i++ )
1602 c = toupper (ioparm.namelist_name[i]);
1603 write_character (&c ,1);
1612 t1 = nml_write_obj (t2, dummy_offset, dummy, dummy_name);
1615 write_character (" /\n", 4);
1617 /* Recover the original delimiter. */
1619 current_unit->flags.delim = tmp_delim;