re PR target/23552 (FAIL: gfortran.dg/large_real_kind_1.f90)
[gcc.git] / libgfortran / io / write.c
1 /* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
3 Namelist output contibuted by Paul Thomas
4
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6
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.
11
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.)
20
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.
25
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. */
30
31 #include "config.h"
32 #include <string.h>
33 #include <ctype.h>
34 #include <float.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include "libgfortran.h"
38 #include "io.h"
39
40 #define star_fill(p, n) memset(p, '*', n)
41
42
43 typedef enum
44 { SIGN_NONE, SIGN_MINUS, SIGN_PLUS }
45 sign_t;
46
47
48 static int no_leading_blank = 0 ;
49
50 void
51 write_a (fnode * f, const char *source, int len)
52 {
53 int wlen;
54 char *p;
55
56 wlen = f->u.string.length < 0 ? len : f->u.string.length;
57
58 p = write_block (wlen);
59 if (p == NULL)
60 return;
61
62 if (wlen < len)
63 memcpy (p, source, wlen);
64 else
65 {
66 memset (p, ' ', wlen - len);
67 memcpy (p + wlen - len, source, len);
68 }
69 }
70
71 static GFC_INTEGER_LARGEST
72 extract_int (const void *p, int len)
73 {
74 GFC_INTEGER_LARGEST i = 0;
75
76 if (p == NULL)
77 return i;
78
79 switch (len)
80 {
81 case 1:
82 {
83 GFC_INTEGER_1 tmp;
84 memcpy ((void *) &tmp, p, len);
85 i = tmp;
86 }
87 break;
88 case 2:
89 {
90 GFC_INTEGER_2 tmp;
91 memcpy ((void *) &tmp, p, len);
92 i = tmp;
93 }
94 break;
95 case 4:
96 {
97 GFC_INTEGER_4 tmp;
98 memcpy ((void *) &tmp, p, len);
99 i = tmp;
100 }
101 break;
102 case 8:
103 {
104 GFC_INTEGER_8 tmp;
105 memcpy ((void *) &tmp, p, len);
106 i = tmp;
107 }
108 break;
109 #ifdef HAVE_GFC_INTEGER_16
110 case 16:
111 {
112 GFC_INTEGER_16 tmp;
113 memcpy ((void *) &tmp, p, len);
114 i = tmp;
115 }
116 break;
117 #endif
118 default:
119 internal_error ("bad integer kind");
120 }
121
122 return i;
123 }
124
125 static GFC_UINTEGER_LARGEST
126 extract_uint (const void *p, int len)
127 {
128 GFC_UINTEGER_LARGEST i = 0;
129
130 if (p == NULL)
131 return i;
132
133 switch (len)
134 {
135 case 1:
136 {
137 GFC_INTEGER_1 tmp;
138 memcpy ((void *) &tmp, p, len);
139 i = (GFC_UINTEGER_1) tmp;
140 }
141 break;
142 case 2:
143 {
144 GFC_INTEGER_2 tmp;
145 memcpy ((void *) &tmp, p, len);
146 i = (GFC_UINTEGER_2) tmp;
147 }
148 break;
149 case 4:
150 {
151 GFC_INTEGER_4 tmp;
152 memcpy ((void *) &tmp, p, len);
153 i = (GFC_UINTEGER_4) tmp;
154 }
155 break;
156 case 8:
157 {
158 GFC_INTEGER_8 tmp;
159 memcpy ((void *) &tmp, p, len);
160 i = (GFC_UINTEGER_8) tmp;
161 }
162 break;
163 #ifdef HAVE_GFC_INTEGER_16
164 case 16:
165 {
166 GFC_INTEGER_16 tmp;
167 memcpy ((void *) &tmp, p, len);
168 i = (GFC_UINTEGER_16) tmp;
169 }
170 break;
171 #endif
172 default:
173 internal_error ("bad integer kind");
174 }
175
176 return i;
177 }
178
179 static GFC_REAL_LARGEST
180 extract_real (const void *p, int len)
181 {
182 GFC_REAL_LARGEST i = 0;
183 switch (len)
184 {
185 case 4:
186 {
187 GFC_REAL_4 tmp;
188 memcpy ((void *) &tmp, p, len);
189 i = tmp;
190 }
191 break;
192 case 8:
193 {
194 GFC_REAL_8 tmp;
195 memcpy ((void *) &tmp, p, len);
196 i = tmp;
197 }
198 break;
199 #ifdef HAVE_GFC_REAL_10
200 case 10:
201 {
202 GFC_REAL_10 tmp;
203 memcpy ((void *) &tmp, p, len);
204 i = tmp;
205 }
206 break;
207 #endif
208 #ifdef HAVE_GFC_REAL_16
209 case 16:
210 {
211 GFC_REAL_16 tmp;
212 memcpy ((void *) &tmp, p, len);
213 i = tmp;
214 }
215 break;
216 #endif
217 default:
218 internal_error ("bad real kind");
219 }
220 return i;
221 }
222
223
224 /* Given a flag that indicate if a value is negative or not, return a
225 sign_t that gives the sign that we need to produce. */
226
227 static sign_t
228 calculate_sign (int negative_flag)
229 {
230 sign_t s = SIGN_NONE;
231
232 if (negative_flag)
233 s = SIGN_MINUS;
234 else
235 switch (g.sign_status)
236 {
237 case SIGN_SP:
238 s = SIGN_PLUS;
239 break;
240 case SIGN_SS:
241 s = SIGN_NONE;
242 break;
243 case SIGN_S:
244 s = options.optional_plus ? SIGN_PLUS : SIGN_NONE;
245 break;
246 }
247
248 return s;
249 }
250
251
252 /* Returns the value of 10**d. */
253
254 static GFC_REAL_LARGEST
255 calculate_exp (int d)
256 {
257 int i;
258 GFC_REAL_LARGEST r = 1.0;
259
260 for (i = 0; i< (d >= 0 ? d : -d); i++)
261 r *= 10;
262
263 r = (d >= 0) ? r : 1.0 / r;
264
265 return r;
266 }
267
268
269 /* Generate corresponding I/O format for FMT_G output.
270 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
271 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
272
273 Data Magnitude Equivalent Conversion
274 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
275 m = 0 F(w-n).(d-1), n' '
276 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
277 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
278 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
279 ................ ..........
280 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
281 m >= 10**d-0.5 Ew.d[Ee]
282
283 notes: for Gw.d , n' ' means 4 blanks
284 for Gw.dEe, n' ' means e+2 blanks */
285
286 static fnode *
287 calculate_G_format (fnode *f, GFC_REAL_LARGEST value, int *num_blank)
288 {
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;
296
297 newf = get_mem (sizeof (fnode));
298
299 /* Absolute value. */
300 m = (value > 0.0) ? value : -value;
301
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 {
307 newf->format = FMT_E;
308 newf->u.real.w = w;
309 newf->u.real.d = d;
310 newf->u.real.e = e;
311 *num_blank = 0;
312 return newf;
313 }
314
315 /* Use binary search to find the data magnitude range. */
316 mid = 0;
317 low = 0;
318 high = d + 1;
319 lbound = 0;
320 ubound = d + 1;
321
322 while (low <= high)
323 {
324 GFC_REAL_LARGEST temp;
325 mid = (low + high) / 2;
326
327 /* 0.1 * 10**mid - 0.5 * 10**(mid-d-1) */
328 temp = 0.1 * calculate_exp (mid) - 0.5 * calculate_exp (mid - d - 1);
329
330 if (m < temp)
331 {
332 ubound = mid;
333 if (ubound == lbound + 1)
334 break;
335 high = mid - 1;
336 }
337 else if (m > temp)
338 {
339 lbound = mid;
340 if (ubound == lbound + 1)
341 {
342 mid ++;
343 break;
344 }
345 low = mid + 1;
346 }
347 else
348 break;
349 }
350
351 /* Pad with blanks where the exponent would be. */
352 if (e < 0)
353 *num_blank = 4;
354 else
355 *num_blank = e + 2;
356
357 /* Generate the F editing. F(w-n).(-(mid-d-1)), n' '. */
358 newf->format = FMT_F;
359 newf->u.real.w = f->u.real.w - *num_blank;
360
361 /* Special case. */
362 if (m == 0.0)
363 newf->u.real.d = d - 1;
364 else
365 newf->u.real.d = - (mid - d - 1);
366
367 /* For F editing, the scale factor is ignored. */
368 g.scale_factor = 0;
369 return newf;
370 }
371
372
373 /* Output a real number according to its format which is FMT_G free. */
374
375 static void
376 output_float (fnode *f, GFC_REAL_LARGEST value)
377 {
378 /* This must be large enough to accurately hold any value. */
379 char buffer[32];
380 char *out;
381 char *digits;
382 int e;
383 char expchar;
384 format_token ft;
385 int w;
386 int d;
387 int edigits;
388 int ndigits;
389 /* Number of digits before the decimal point. */
390 int nbefore;
391 /* Number of zeros after the decimal point. */
392 int nzero;
393 /* Number of digits after the decimal point. */
394 int nafter;
395 /* Number of zeros after the decimal point, whatever the precision. */
396 int nzero_real;
397 int leadzero;
398 int nblanks;
399 int i;
400 sign_t sign;
401 double abslog;
402
403 ft = f->format;
404 w = f->u.real.w;
405 d = f->u.real.d;
406
407 nzero_real = -1;
408
409
410 /* We should always know the field width and precision. */
411 if (d < 0)
412 internal_error ("Unspecified precision");
413
414 /* Use sprintf to print the number in the format +D.DDDDe+ddd
415 For an N digit exponent, this gives us (32-6)-N digits after the
416 decimal point, plus another one before the decimal point. */
417 sign = calculate_sign (value < 0.0);
418 if (value < 0)
419 value = -value;
420
421 /* Printf always prints at least two exponent digits. */
422 if (value == 0)
423 edigits = 2;
424 else
425 {
426 #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
427 abslog = fabs((double) log10l(value));
428 #else
429 abslog = fabs(log10(value));
430 #endif
431 if (abslog < 100)
432 edigits = 2;
433 else
434 edigits = 1 + (int) log10(abslog);
435 }
436
437 if (ft == FMT_F || ft == FMT_EN
438 || ((ft == FMT_D || ft == FMT_E) && g.scale_factor != 0))
439 {
440 /* Always convert at full precision to avoid double rounding. */
441 ndigits = 27 - edigits;
442 }
443 else
444 {
445 /* We know the number of digits, so can let printf do the rounding
446 for us. */
447 if (ft == FMT_ES)
448 ndigits = d + 1;
449 else
450 ndigits = d;
451 if (ndigits > 27 - edigits)
452 ndigits = 27 - edigits;
453 }
454
455 /* # The result will always contain a decimal point, even if no
456 * digits follow it
457 *
458 * - The converted value is to be left adjusted on the field boundary
459 *
460 * + A sign (+ or -) always be placed before a number
461 *
462 * 31 minimum field width
463 *
464 * * (ndigits-1) is used as the precision
465 *
466 * e format: [-]d.ddde±dd where there is one digit before the
467 * decimal-point character and the number of digits after it is
468 * equal to the precision. The exponent always contains at least two
469 * digits; if the value is zero, the exponent is 00.
470 */
471 sprintf (buffer, "%+-#31.*" GFC_REAL_LARGEST_FORMAT "e",
472 ndigits - 1, value);
473
474 /* Check the resulting string has punctuation in the correct places. */
475 if (buffer[2] != '.' || buffer[ndigits + 2] != 'e')
476 internal_error ("printf is broken");
477
478 /* Read the exponent back in. */
479 e = atoi (&buffer[ndigits + 3]) + 1;
480
481 /* Make sure zero comes out as 0.0e0. */
482 if (value == 0.0)
483 e = 0;
484
485 /* Normalize the fractional component. */
486 buffer[2] = buffer[1];
487 digits = &buffer[2];
488
489 /* Figure out where to place the decimal point. */
490 switch (ft)
491 {
492 case FMT_F:
493 nbefore = e + g.scale_factor;
494 if (nbefore < 0)
495 {
496 nzero = -nbefore;
497 nzero_real = nzero;
498 if (nzero > d)
499 nzero = d;
500 nafter = d - nzero;
501 nbefore = 0;
502 }
503 else
504 {
505 nzero = 0;
506 nafter = d;
507 }
508 expchar = 0;
509 break;
510
511 case FMT_E:
512 case FMT_D:
513 i = g.scale_factor;
514 if (value != 0.0)
515 e -= i;
516 if (i < 0)
517 {
518 nbefore = 0;
519 nzero = -i;
520 nafter = d + i;
521 }
522 else if (i > 0)
523 {
524 nbefore = i;
525 nzero = 0;
526 nafter = (d - i) + 1;
527 }
528 else /* i == 0 */
529 {
530 nbefore = 0;
531 nzero = 0;
532 nafter = d;
533 }
534
535 if (ft == FMT_E)
536 expchar = 'E';
537 else
538 expchar = 'D';
539 break;
540
541 case FMT_EN:
542 /* The exponent must be a multiple of three, with 1-3 digits before
543 the decimal point. */
544 if (value != 0.0)
545 e--;
546 if (e >= 0)
547 nbefore = e % 3;
548 else
549 {
550 nbefore = (-e) % 3;
551 if (nbefore != 0)
552 nbefore = 3 - nbefore;
553 }
554 e -= nbefore;
555 nbefore++;
556 nzero = 0;
557 nafter = d;
558 expchar = 'E';
559 break;
560
561 case FMT_ES:
562 if (value != 0.0)
563 e--;
564 nbefore = 1;
565 nzero = 0;
566 nafter = d;
567 expchar = 'E';
568 break;
569
570 default:
571 /* Should never happen. */
572 internal_error ("Unexpected format token");
573 }
574
575 /* Round the value. */
576 if (nbefore + nafter == 0)
577 {
578 ndigits = 0;
579 if (nzero_real == d && digits[0] >= '5')
580 {
581 /* We rounded to zero but shouldn't have */
582 nzero--;
583 nafter = 1;
584 digits[0] = '1';
585 ndigits = 1;
586 }
587 }
588 else if (nbefore + nafter < ndigits)
589 {
590 ndigits = nbefore + nafter;
591 i = ndigits;
592 if (digits[i] >= '5')
593 {
594 /* Propagate the carry. */
595 for (i--; i >= 0; i--)
596 {
597 if (digits[i] != '9')
598 {
599 digits[i]++;
600 break;
601 }
602 digits[i] = '0';
603 }
604
605 if (i < 0)
606 {
607 /* The carry overflowed. Fortunately we have some spare space
608 at the start of the buffer. We may discard some digits, but
609 this is ok because we already know they are zero. */
610 digits--;
611 digits[0] = '1';
612 if (ft == FMT_F)
613 {
614 if (nzero > 0)
615 {
616 nzero--;
617 nafter++;
618 }
619 else
620 nbefore++;
621 }
622 else if (ft == FMT_EN)
623 {
624 nbefore++;
625 if (nbefore == 4)
626 {
627 nbefore = 1;
628 e += 3;
629 }
630 }
631 else
632 e++;
633 }
634 }
635 }
636
637 /* Calculate the format of the exponent field. */
638 if (expchar)
639 {
640 edigits = 1;
641 for (i = abs (e); i >= 10; i /= 10)
642 edigits++;
643
644 if (f->u.real.e < 0)
645 {
646 /* Width not specified. Must be no more than 3 digits. */
647 if (e > 999 || e < -999)
648 edigits = -1;
649 else
650 {
651 edigits = 4;
652 if (e > 99 || e < -99)
653 expchar = ' ';
654 }
655 }
656 else
657 {
658 /* Exponent width specified, check it is wide enough. */
659 if (edigits > f->u.real.e)
660 edigits = -1;
661 else
662 edigits = f->u.real.e + 2;
663 }
664 }
665 else
666 edigits = 0;
667
668 /* Pick a field size if none was specified. */
669 if (w <= 0)
670 w = nbefore + nzero + nafter + (sign != SIGN_NONE ? 2 : 1);
671
672 /* Create the ouput buffer. */
673 out = write_block (w);
674 if (out == NULL)
675 return;
676
677 /* Zero values always output as positive, even if the value was negative
678 before rounding. */
679 for (i = 0; i < ndigits; i++)
680 {
681 if (digits[i] != '0')
682 break;
683 }
684 if (i == ndigits)
685 sign = calculate_sign (0);
686
687 /* Work out how much padding is needed. */
688 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
689 if (sign != SIGN_NONE)
690 nblanks--;
691
692 /* Check the value fits in the specified field width. */
693 if (nblanks < 0 || edigits == -1)
694 {
695 star_fill (out, w);
696 return;
697 }
698
699 /* See if we have space for a zero before the decimal point. */
700 if (nbefore == 0 && nblanks > 0)
701 {
702 leadzero = 1;
703 nblanks--;
704 }
705 else
706 leadzero = 0;
707
708 /* Pad to full field width. */
709
710
711 if ( ( nblanks > 0 ) && !no_leading_blank )
712 {
713 memset (out, ' ', nblanks);
714 out += nblanks;
715 }
716
717 /* Output the initial sign (if any). */
718 if (sign == SIGN_PLUS)
719 *(out++) = '+';
720 else if (sign == SIGN_MINUS)
721 *(out++) = '-';
722
723 /* Output an optional leading zero. */
724 if (leadzero)
725 *(out++) = '0';
726
727 /* Output the part before the decimal point, padding with zeros. */
728 if (nbefore > 0)
729 {
730 if (nbefore > ndigits)
731 i = ndigits;
732 else
733 i = nbefore;
734
735 memcpy (out, digits, i);
736 while (i < nbefore)
737 out[i++] = '0';
738
739 digits += i;
740 ndigits -= i;
741 out += nbefore;
742 }
743 /* Output the decimal point. */
744 *(out++) = '.';
745
746 /* Output leading zeros after the decimal point. */
747 if (nzero > 0)
748 {
749 for (i = 0; i < nzero; i++)
750 *(out++) = '0';
751 }
752
753 /* Output digits after the decimal point, padding with zeros. */
754 if (nafter > 0)
755 {
756 if (nafter > ndigits)
757 i = ndigits;
758 else
759 i = nafter;
760
761 memcpy (out, digits, i);
762 while (i < nafter)
763 out[i++] = '0';
764
765 digits += i;
766 ndigits -= i;
767 out += nafter;
768 }
769
770 /* Output the exponent. */
771 if (expchar)
772 {
773 if (expchar != ' ')
774 {
775 *(out++) = expchar;
776 edigits--;
777 }
778 #if HAVE_SNPRINTF
779 snprintf (buffer, 32, "%+0*d", edigits, e);
780 #else
781 sprintf (buffer, "%+0*d", edigits, e);
782 #endif
783 memcpy (out, buffer, edigits);
784 }
785
786 if ( no_leading_blank )
787 {
788 out += edigits;
789 memset( out , ' ' , nblanks );
790 no_leading_blank = 0;
791 }
792 }
793
794
795 void
796 write_l (fnode * f, char *source, int len)
797 {
798 char *p;
799 GFC_INTEGER_LARGEST n;
800
801 p = write_block (f->u.w);
802 if (p == NULL)
803 return;
804
805 memset (p, ' ', f->u.w - 1);
806 n = extract_int (source, len);
807 p[f->u.w - 1] = (n) ? 'T' : 'F';
808 }
809
810 /* Output a real number according to its format. */
811
812 static void
813 write_float (fnode *f, const char *source, int len)
814 {
815 GFC_REAL_LARGEST n;
816 int nb =0, res, save_scale_factor;
817 char * p, fin;
818 fnode *f2 = NULL;
819
820 n = extract_real (source, len);
821
822 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
823 {
824 res = isfinite (n);
825 if (res == 0)
826 {
827 nb = f->u.real.w;
828
829 /* If the field width is zero, the processor must select a width
830 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
831
832 if (nb == 0) nb = 4;
833 p = write_block (nb);
834 if (nb < 3)
835 {
836 memset (p, '*',nb);
837 return;
838 }
839
840 memset(p, ' ', nb);
841 res = !isnan (n);
842 if (res != 0)
843 {
844 if (signbit(n))
845 {
846
847 /* If the sign is negative and the width is 3, there is
848 insufficient room to output '-Inf', so output asterisks */
849
850 if (nb == 3)
851 {
852 memset (p, '*',nb);
853 return;
854 }
855
856 /* The negative sign is mandatory */
857
858 fin = '-';
859 }
860 else
861
862 /* The positive sign is optional, but we output it for
863 consistency */
864
865 fin = '+';
866
867 if (nb > 8)
868
869 /* We have room, so output 'Infinity' */
870
871 memcpy(p + nb - 8, "Infinity", 8);
872 else
873
874 /* For the case of width equals 8, there is not enough room
875 for the sign and 'Infinity' so we go with 'Inf' */
876
877 memcpy(p + nb - 3, "Inf", 3);
878 if (nb < 9 && nb > 3)
879 p[nb - 4] = fin; /* Put the sign in front of Inf */
880 else if (nb > 8)
881 p[nb - 9] = fin; /* Put the sign in front of Infinity */
882 }
883 else
884 memcpy(p + nb - 3, "NaN", 3);
885 return;
886 }
887 }
888
889 if (f->format != FMT_G)
890 {
891 output_float (f, n);
892 }
893 else
894 {
895 save_scale_factor = g.scale_factor;
896 f2 = calculate_G_format(f, n, &nb);
897 output_float (f2, n);
898 g.scale_factor = save_scale_factor;
899 if (f2 != NULL)
900 free_mem(f2);
901
902 if (nb > 0)
903 {
904 p = write_block (nb);
905 memset (p, ' ', nb);
906 }
907 }
908 }
909
910
911 static void
912 write_int (fnode *f, const char *source, int len,
913 char *(*conv) (GFC_UINTEGER_LARGEST))
914 {
915 GFC_UINTEGER_LARGEST n = 0;
916 int w, m, digits, nzero, nblank;
917 char *p, *q;
918
919 w = f->u.integer.w;
920 m = f->u.integer.m;
921
922 n = extract_uint (source, len);
923
924 /* Special case: */
925
926 if (m == 0 && n == 0)
927 {
928 if (w == 0)
929 w = 1;
930
931 p = write_block (w);
932 if (p == NULL)
933 return;
934
935 memset (p, ' ', w);
936 goto done;
937 }
938
939 q = conv (n);
940 digits = strlen (q);
941
942 /* Select a width if none was specified. The idea here is to always
943 print something. */
944
945 if (w == 0)
946 w = ((digits < m) ? m : digits);
947
948 p = write_block (w);
949 if (p == NULL)
950 return;
951
952 nzero = 0;
953 if (digits < m)
954 nzero = m - digits;
955
956 /* See if things will work. */
957
958 nblank = w - (nzero + digits);
959
960 if (nblank < 0)
961 {
962 star_fill (p, w);
963 goto done;
964 }
965
966
967 if (!no_leading_blank)
968 {
969 memset (p, ' ', nblank);
970 p += nblank;
971 memset (p, '0', nzero);
972 p += nzero;
973 memcpy (p, q, digits);
974 }
975 else
976 {
977 memset (p, '0', nzero);
978 p += nzero;
979 memcpy (p, q, digits);
980 p += digits;
981 memset (p, ' ', nblank);
982 no_leading_blank = 0;
983 }
984
985 done:
986 return;
987 }
988
989 static void
990 write_decimal (fnode *f, const char *source, int len,
991 char *(*conv) (GFC_INTEGER_LARGEST))
992 {
993 GFC_INTEGER_LARGEST n = 0;
994 int w, m, digits, nsign, nzero, nblank;
995 char *p, *q;
996 sign_t sign;
997
998 w = f->u.integer.w;
999 m = f->u.integer.m;
1000
1001 n = extract_int (source, len);
1002
1003 /* Special case: */
1004
1005 if (m == 0 && n == 0)
1006 {
1007 if (w == 0)
1008 w = 1;
1009
1010 p = write_block (w);
1011 if (p == NULL)
1012 return;
1013
1014 memset (p, ' ', w);
1015 goto done;
1016 }
1017
1018 sign = calculate_sign (n < 0);
1019 if (n < 0)
1020 n = -n;
1021
1022 nsign = sign == SIGN_NONE ? 0 : 1;
1023 q = conv (n);
1024
1025 digits = strlen (q);
1026
1027 /* Select a width if none was specified. The idea here is to always
1028 print something. */
1029
1030 if (w == 0)
1031 w = ((digits < m) ? m : digits) + nsign;
1032
1033 p = write_block (w);
1034 if (p == NULL)
1035 return;
1036
1037 nzero = 0;
1038 if (digits < m)
1039 nzero = m - digits;
1040
1041 /* See if things will work. */
1042
1043 nblank = w - (nsign + nzero + digits);
1044
1045 if (nblank < 0)
1046 {
1047 star_fill (p, w);
1048 goto done;
1049 }
1050
1051 memset (p, ' ', nblank);
1052 p += nblank;
1053
1054 switch (sign)
1055 {
1056 case SIGN_PLUS:
1057 *p++ = '+';
1058 break;
1059 case SIGN_MINUS:
1060 *p++ = '-';
1061 break;
1062 case SIGN_NONE:
1063 break;
1064 }
1065
1066 memset (p, '0', nzero);
1067 p += nzero;
1068
1069 memcpy (p, q, digits);
1070
1071 done:
1072 return;
1073 }
1074
1075
1076 /* Convert unsigned octal to ascii. */
1077
1078 static char *
1079 otoa (GFC_UINTEGER_LARGEST n)
1080 {
1081 char *p;
1082
1083 if (n == 0)
1084 {
1085 scratch[0] = '0';
1086 scratch[1] = '\0';
1087 return scratch;
1088 }
1089
1090 p = scratch + SCRATCH_SIZE - 1;
1091 *p-- = '\0';
1092
1093 while (n != 0)
1094 {
1095 *p = '0' + (n & 7);
1096 p--;
1097 n >>= 3;
1098 }
1099
1100 return ++p;
1101 }
1102
1103
1104 /* Convert unsigned binary to ascii. */
1105
1106 static char *
1107 btoa (GFC_UINTEGER_LARGEST n)
1108 {
1109 char *p;
1110
1111 if (n == 0)
1112 {
1113 scratch[0] = '0';
1114 scratch[1] = '\0';
1115 return scratch;
1116 }
1117
1118 p = scratch + SCRATCH_SIZE - 1;
1119 *p-- = '\0';
1120
1121 while (n != 0)
1122 {
1123 *p-- = '0' + (n & 1);
1124 n >>= 1;
1125 }
1126
1127 return ++p;
1128 }
1129
1130
1131 void
1132 write_i (fnode * f, const char *p, int len)
1133 {
1134 write_decimal (f, p, len, (void *) gfc_itoa);
1135 }
1136
1137
1138 void
1139 write_b (fnode * f, const char *p, int len)
1140 {
1141 write_int (f, p, len, btoa);
1142 }
1143
1144
1145 void
1146 write_o (fnode * f, const char *p, int len)
1147 {
1148 write_int (f, p, len, otoa);
1149 }
1150
1151 void
1152 write_z (fnode * f, const char *p, int len)
1153 {
1154 write_int (f, p, len, xtoa);
1155 }
1156
1157
1158 void
1159 write_d (fnode *f, const char *p, int len)
1160 {
1161 write_float (f, p, len);
1162 }
1163
1164
1165 void
1166 write_e (fnode *f, const char *p, int len)
1167 {
1168 write_float (f, p, len);
1169 }
1170
1171
1172 void
1173 write_f (fnode *f, const char *p, int len)
1174 {
1175 write_float (f, p, len);
1176 }
1177
1178
1179 void
1180 write_en (fnode *f, const char *p, int len)
1181 {
1182 write_float (f, p, len);
1183 }
1184
1185
1186 void
1187 write_es (fnode *f, const char *p, int len)
1188 {
1189 write_float (f, p, len);
1190 }
1191
1192
1193 /* Take care of the X/TR descriptor. */
1194
1195 void
1196 write_x (int len, int nspaces)
1197 {
1198 char *p;
1199
1200 p = write_block (len);
1201 if (p == NULL)
1202 return;
1203
1204 if (nspaces > 0)
1205 memset (&p[len - nspaces], ' ', nspaces);
1206 }
1207
1208
1209 /* List-directed writing. */
1210
1211
1212 /* Write a single character to the output. Returns nonzero if
1213 something goes wrong. */
1214
1215 static int
1216 write_char (char c)
1217 {
1218 char *p;
1219
1220 p = write_block (1);
1221 if (p == NULL)
1222 return 1;
1223
1224 *p = c;
1225
1226 return 0;
1227 }
1228
1229
1230 /* Write a list-directed logical value. */
1231
1232 static void
1233 write_logical (const char *source, int length)
1234 {
1235 write_char (extract_int (source, length) ? 'T' : 'F');
1236 }
1237
1238
1239 /* Write a list-directed integer value. */
1240
1241 static void
1242 write_integer (const char *source, int length)
1243 {
1244 char *p;
1245 const char *q;
1246 int digits;
1247 int width;
1248
1249 q = gfc_itoa (extract_int (source, length));
1250
1251 switch (length)
1252 {
1253 case 1:
1254 width = 4;
1255 break;
1256
1257 case 2:
1258 width = 6;
1259 break;
1260
1261 case 4:
1262 width = 11;
1263 break;
1264
1265 case 8:
1266 width = 20;
1267 break;
1268
1269 default:
1270 width = 0;
1271 break;
1272 }
1273
1274 digits = strlen (q);
1275
1276 if(width < digits )
1277 width = digits ;
1278 p = write_block (width) ;
1279 if (no_leading_blank)
1280 {
1281 memcpy (p, q, digits);
1282 memset(p + digits ,' ', width - digits) ;
1283 }
1284 else
1285 {
1286 memset(p ,' ', width - digits) ;
1287 memcpy (p + width - digits, q, digits);
1288 }
1289 }
1290
1291
1292 /* Write a list-directed string. We have to worry about delimiting
1293 the strings if the file has been opened in that mode. */
1294
1295 static void
1296 write_character (const char *source, int length)
1297 {
1298 int i, extra;
1299 char *p, d;
1300
1301 switch (current_unit->flags.delim)
1302 {
1303 case DELIM_APOSTROPHE:
1304 d = '\'';
1305 break;
1306 case DELIM_QUOTE:
1307 d = '"';
1308 break;
1309 default:
1310 d = ' ';
1311 break;
1312 }
1313
1314 if (d == ' ')
1315 extra = 0;
1316 else
1317 {
1318 extra = 2;
1319
1320 for (i = 0; i < length; i++)
1321 if (source[i] == d)
1322 extra++;
1323 }
1324
1325 p = write_block (length + extra);
1326 if (p == NULL)
1327 return;
1328
1329 if (d == ' ')
1330 memcpy (p, source, length);
1331 else
1332 {
1333 *p++ = d;
1334
1335 for (i = 0; i < length; i++)
1336 {
1337 *p++ = source[i];
1338 if (source[i] == d)
1339 *p++ = d;
1340 }
1341
1342 *p = d;
1343 }
1344 }
1345
1346
1347 /* Output a real number with default format.
1348 This is 1PG14.7E2 for REAL(4), 1PG23.15E3 for REAL(8),
1349 1PG24.15E4 for REAL(10) and 1PG40.31E4 for REAL(16). */
1350
1351 static void
1352 write_real (const char *source, int length)
1353 {
1354 fnode f ;
1355 int org_scale = g.scale_factor;
1356 f.format = FMT_G;
1357 g.scale_factor = 1;
1358 switch (length)
1359 {
1360 case 4:
1361 f.u.real.w = 14;
1362 f.u.real.d = 7;
1363 f.u.real.e = 2;
1364 break;
1365 case 8:
1366 f.u.real.w = 23;
1367 f.u.real.d = 15;
1368 f.u.real.e = 3;
1369 break;
1370 case 10:
1371 f.u.real.w = 24;
1372 f.u.real.d = 15;
1373 f.u.real.e = 4;
1374 break;
1375 case 16:
1376 f.u.real.w = 40;
1377 f.u.real.d = 31;
1378 f.u.real.e = 4;
1379 break;
1380 default:
1381 internal_error ("bad real kind");
1382 break;
1383 }
1384 write_float (&f, source , length);
1385 g.scale_factor = org_scale;
1386 }
1387
1388
1389 static void
1390 write_complex (const char *source, int len)
1391 {
1392 if (write_char ('('))
1393 return;
1394 write_real (source, len);
1395
1396 if (write_char (','))
1397 return;
1398 write_real (source + len, len);
1399
1400 write_char (')');
1401 }
1402
1403
1404 /* Write the separator between items. */
1405
1406 static void
1407 write_separator (void)
1408 {
1409 char *p;
1410
1411 p = write_block (options.separator_len);
1412 if (p == NULL)
1413 return;
1414
1415 memcpy (p, options.separator, options.separator_len);
1416 }
1417
1418
1419 /* Write an item with list formatting.
1420 TODO: handle skipping to the next record correctly, particularly
1421 with strings. */
1422
1423 static void
1424 list_formatted_write_scalar (bt type, void *p, int len)
1425 {
1426 static int char_flag;
1427
1428 if (current_unit == NULL)
1429 return;
1430
1431 if (g.first_item)
1432 {
1433 g.first_item = 0;
1434 char_flag = 0;
1435 write_char (' ');
1436 }
1437 else
1438 {
1439 if (type != BT_CHARACTER || !char_flag ||
1440 current_unit->flags.delim != DELIM_NONE)
1441 write_separator ();
1442 }
1443
1444 switch (type)
1445 {
1446 case BT_INTEGER:
1447 write_integer (p, len);
1448 break;
1449 case BT_LOGICAL:
1450 write_logical (p, len);
1451 break;
1452 case BT_CHARACTER:
1453 write_character (p, len);
1454 break;
1455 case BT_REAL:
1456 write_real (p, len);
1457 break;
1458 case BT_COMPLEX:
1459 write_complex (p, len);
1460 break;
1461 default:
1462 internal_error ("list_formatted_write(): Bad type");
1463 }
1464
1465 char_flag = (type == BT_CHARACTER);
1466 }
1467
1468
1469 void
1470 list_formatted_write (bt type, void *p, int len, size_t nelems)
1471 {
1472 size_t elem;
1473 int size;
1474 char *tmp;
1475
1476 tmp = (char *) p;
1477
1478 if (type == BT_COMPLEX)
1479 size = 2 * len;
1480 else
1481 size = len;
1482
1483 /* Big loop over all the elements. */
1484 for (elem = 0; elem < nelems; elem++)
1485 {
1486 g.item_count++;
1487 list_formatted_write_scalar (type, tmp + size*elem, len);
1488 }
1489 }
1490
1491 /* NAMELIST OUTPUT
1492
1493 nml_write_obj writes a namelist object to the output stream. It is called
1494 recursively for derived type components:
1495 obj = is the namelist_info for the current object.
1496 offset = the offset relative to the address held by the object for
1497 derived type arrays.
1498 base = is the namelist_info of the derived type, when obj is a
1499 component.
1500 base_name = the full name for a derived type, including qualifiers
1501 if any.
1502 The returned value is a pointer to the object beyond the last one
1503 accessed, including nested derived types. Notice that the namelist is
1504 a linear linked list of objects, including derived types and their
1505 components. A tree, of sorts, is implied by the compound names of
1506 the derived type components and this is how this function recurses through
1507 the list. */
1508
1509 /* A generous estimate of the number of characters needed to print
1510 repeat counts and indices, including commas, asterices and brackets. */
1511
1512 #define NML_DIGITS 20
1513
1514 /* Stores the delimiter to be used for character objects. */
1515
1516 static const char * nml_delim;
1517
1518 static namelist_info *
1519 nml_write_obj (namelist_info * obj, index_type offset,
1520 namelist_info * base, char * base_name)
1521 {
1522 int rep_ctr;
1523 int num;
1524 int nml_carry;
1525 index_type len;
1526 index_type obj_size;
1527 index_type nelem;
1528 index_type dim_i;
1529 index_type clen;
1530 index_type elem_ctr;
1531 index_type obj_name_len;
1532 void * p ;
1533 char cup;
1534 char * obj_name;
1535 char * ext_name;
1536 char rep_buff[NML_DIGITS];
1537 namelist_info * cmp;
1538 namelist_info * retval = obj->next;
1539
1540 /* Write namelist variable names in upper case. If a derived type,
1541 nothing is output. If a component, base and base_name are set. */
1542
1543 if (obj->type != GFC_DTYPE_DERIVED)
1544 {
1545 write_character ("\n ", 2);
1546 len = 0;
1547 if (base)
1548 {
1549 len =strlen (base->var_name);
1550 for (dim_i = 0; dim_i < (index_type) strlen (base_name); dim_i++)
1551 {
1552 cup = toupper (base_name[dim_i]);
1553 write_character (&cup, 1);
1554 }
1555 }
1556 for (dim_i =len; dim_i < (index_type) strlen (obj->var_name); dim_i++)
1557 {
1558 cup = toupper (obj->var_name[dim_i]);
1559 write_character (&cup, 1);
1560 }
1561 write_character ("=", 1);
1562 }
1563
1564 /* Counts the number of data output on a line, including names. */
1565
1566 num = 1;
1567
1568 len = obj->len;
1569 obj_size = len;
1570 if (obj->type == GFC_DTYPE_COMPLEX)
1571 obj_size = 2*len;
1572 if (obj->type == GFC_DTYPE_CHARACTER)
1573 obj_size = obj->string_length;
1574 if (obj->var_rank)
1575 obj_size = obj->size;
1576
1577 /* Set the index vector and count the number of elements. */
1578
1579 nelem = 1;
1580 for (dim_i=0; dim_i < obj->var_rank; dim_i++)
1581 {
1582 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1583 nelem = nelem * (obj->dim[dim_i].ubound + 1 - obj->dim[dim_i].lbound);
1584 }
1585
1586 /* Main loop to output the data held in the object. */
1587
1588 rep_ctr = 1;
1589 for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
1590 {
1591
1592 /* Build the pointer to the data value. The offset is passed by
1593 recursive calls to this function for arrays of derived types.
1594 Is NULL otherwise. */
1595
1596 p = (void *)(obj->mem_pos + elem_ctr * obj_size);
1597 p += offset;
1598
1599 /* Check for repeat counts of intrinsic types. */
1600
1601 if ((elem_ctr < (nelem - 1)) &&
1602 (obj->type != GFC_DTYPE_DERIVED) &&
1603 !memcmp (p, (void*)(p + obj_size ), obj_size ))
1604 {
1605 rep_ctr++;
1606 }
1607
1608 /* Execute a repeated output. Note the flag no_leading_blank that
1609 is used in the functions used to output the intrinsic types. */
1610
1611 else
1612 {
1613 if (rep_ctr > 1)
1614 {
1615 st_sprintf(rep_buff, " %d*", rep_ctr);
1616 write_character (rep_buff, strlen (rep_buff));
1617 no_leading_blank = 1;
1618 }
1619 num++;
1620
1621 /* Output the data, if an intrinsic type, or recurse into this
1622 routine to treat derived types. */
1623
1624 switch (obj->type)
1625 {
1626
1627 case GFC_DTYPE_INTEGER:
1628 write_integer (p, len);
1629 break;
1630
1631 case GFC_DTYPE_LOGICAL:
1632 write_logical (p, len);
1633 break;
1634
1635 case GFC_DTYPE_CHARACTER:
1636 if (nml_delim)
1637 write_character (nml_delim, 1);
1638 write_character (p, obj->string_length);
1639 if (nml_delim)
1640 write_character (nml_delim, 1);
1641 break;
1642
1643 case GFC_DTYPE_REAL:
1644 write_real (p, len);
1645 break;
1646
1647 case GFC_DTYPE_COMPLEX:
1648 no_leading_blank = 0;
1649 num++;
1650 write_complex (p, len);
1651 break;
1652
1653 case GFC_DTYPE_DERIVED:
1654
1655 /* To treat a derived type, we need to build two strings:
1656 ext_name = the name, including qualifiers that prepends
1657 component names in the output - passed to
1658 nml_write_obj.
1659 obj_name = the derived type name with no qualifiers but %
1660 appended. This is used to identify the
1661 components. */
1662
1663 /* First ext_name => get length of all possible components */
1664
1665 ext_name = (char*)get_mem ( (base_name ? strlen (base_name) : 0)
1666 + (base ? strlen (base->var_name) : 0)
1667 + strlen (obj->var_name)
1668 + obj->var_rank * NML_DIGITS
1669 + 1);
1670
1671 strcpy(ext_name, base_name ? base_name : "");
1672 clen = base ? strlen (base->var_name) : 0;
1673 strcat (ext_name, obj->var_name + clen);
1674
1675 /* Append the qualifier. */
1676
1677 for (dim_i = 0; dim_i < obj->var_rank; dim_i++)
1678 {
1679 strcat (ext_name, dim_i ? "" : "(");
1680 clen = strlen (ext_name);
1681 st_sprintf (ext_name + clen, "%d", (int) obj->ls[dim_i].idx);
1682 strcat (ext_name, (dim_i == obj->var_rank - 1) ? ")" : ",");
1683 }
1684
1685 /* Now obj_name. */
1686
1687 obj_name_len = strlen (obj->var_name) + 1;
1688 obj_name = get_mem (obj_name_len+1);
1689 strcpy (obj_name, obj->var_name);
1690 strcat (obj_name, "%");
1691
1692 /* Now loop over the components. Update the component pointer
1693 with the return value from nml_write_obj => this loop jumps
1694 past nested derived types. */
1695
1696 for (cmp = obj->next;
1697 cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
1698 cmp = retval)
1699 {
1700 retval = nml_write_obj (cmp, (index_type)(p - obj->mem_pos),
1701 obj, ext_name);
1702 }
1703
1704 free_mem (obj_name);
1705 free_mem (ext_name);
1706 goto obj_loop;
1707
1708 default:
1709 internal_error ("Bad type for namelist write");
1710 }
1711
1712 /* Reset the leading blank suppression, write a comma and, if 5
1713 values have been output, write a newline and advance to column
1714 2. Reset the repeat counter. */
1715
1716 no_leading_blank = 0;
1717 write_character (",", 1);
1718 if (num > 5)
1719 {
1720 num = 0;
1721 write_character ("\n ", 2);
1722 }
1723 rep_ctr = 1;
1724 }
1725
1726 /* Cycle through and increment the index vector. */
1727
1728 obj_loop:
1729
1730 nml_carry = 1;
1731 for (dim_i = 0; nml_carry && (dim_i < obj->var_rank); dim_i++)
1732 {
1733 obj->ls[dim_i].idx += nml_carry ;
1734 nml_carry = 0;
1735 if (obj->ls[dim_i].idx > (ssize_t)obj->dim[dim_i].ubound)
1736 {
1737 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1738 nml_carry = 1;
1739 }
1740 }
1741 }
1742
1743 /* Return a pointer beyond the furthest object accessed. */
1744
1745 return retval;
1746 }
1747
1748 /* This is the entry function for namelist writes. It outputs the name
1749 of the namelist and iterates through the namelist by calls to
1750 nml_write_obj. The call below has dummys in the arguments used in
1751 the treatment of derived types. */
1752
1753 void
1754 namelist_write (void)
1755 {
1756 namelist_info * t1, *t2, *dummy = NULL;
1757 index_type i;
1758 index_type dummy_offset = 0;
1759 char c;
1760 char * dummy_name = NULL;
1761 unit_delim tmp_delim;
1762
1763 /* Set the delimiter for namelist output. */
1764
1765 tmp_delim = current_unit->flags.delim;
1766 current_unit->flags.delim = DELIM_NONE;
1767 switch (tmp_delim)
1768 {
1769 case (DELIM_QUOTE):
1770 nml_delim = "\"";
1771 break;
1772
1773 case (DELIM_APOSTROPHE):
1774 nml_delim = "'";
1775 break;
1776
1777 default:
1778 nml_delim = NULL;
1779 }
1780
1781 write_character ("&",1);
1782
1783 /* Write namelist name in upper case - f95 std. */
1784
1785 for (i = 0 ;i < ioparm.namelist_name_len ;i++ )
1786 {
1787 c = toupper (ioparm.namelist_name[i]);
1788 write_character (&c ,1);
1789 }
1790
1791 if (ionml != NULL)
1792 {
1793 t1 = ionml;
1794 while (t1 != NULL)
1795 {
1796 t2 = t1;
1797 t1 = nml_write_obj (t2, dummy_offset, dummy, dummy_name);
1798 }
1799 }
1800 write_character (" /\n", 4);
1801
1802 /* Recover the original delimiter. */
1803
1804 current_unit->flags.delim = tmp_delim;
1805 }
1806
1807 #undef NML_DIGITS