[multiple changes]
[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 /* TODO: there are some systems where isfinite is not able to work
825 with long double variables. We should detect this case and
826 provide our own version for isfinite. */
827 res = isfinite (n);
828 if (res == 0)
829 {
830 nb = f->u.real.w;
831
832 /* If the field width is zero, the processor must select a width
833 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
834
835 if (nb == 0) nb = 4;
836 p = write_block (nb);
837 if (nb < 3)
838 {
839 memset (p, '*',nb);
840 return;
841 }
842
843 memset(p, ' ', nb);
844 res = !isnan (n);
845 if (res != 0)
846 {
847 if (signbit(n))
848 {
849
850 /* If the sign is negative and the width is 3, there is
851 insufficient room to output '-Inf', so output asterisks */
852
853 if (nb == 3)
854 {
855 memset (p, '*',nb);
856 return;
857 }
858
859 /* The negative sign is mandatory */
860
861 fin = '-';
862 }
863 else
864
865 /* The positive sign is optional, but we output it for
866 consistency */
867
868 fin = '+';
869
870 if (nb > 8)
871
872 /* We have room, so output 'Infinity' */
873
874 memcpy(p + nb - 8, "Infinity", 8);
875 else
876
877 /* For the case of width equals 8, there is not enough room
878 for the sign and 'Infinity' so we go with 'Inf' */
879
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 */
885 }
886 else
887 memcpy(p + nb - 3, "NaN", 3);
888 return;
889 }
890 }
891
892 if (f->format != FMT_G)
893 {
894 output_float (f, n);
895 }
896 else
897 {
898 save_scale_factor = g.scale_factor;
899 f2 = calculate_G_format(f, n, &nb);
900 output_float (f2, n);
901 g.scale_factor = save_scale_factor;
902 if (f2 != NULL)
903 free_mem(f2);
904
905 if (nb > 0)
906 {
907 p = write_block (nb);
908 memset (p, ' ', nb);
909 }
910 }
911 }
912
913
914 static void
915 write_int (fnode *f, const char *source, int len,
916 char *(*conv) (GFC_UINTEGER_LARGEST))
917 {
918 GFC_UINTEGER_LARGEST n = 0;
919 int w, m, digits, nzero, nblank;
920 char *p, *q;
921
922 w = f->u.integer.w;
923 m = f->u.integer.m;
924
925 n = extract_uint (source, len);
926
927 /* Special case: */
928
929 if (m == 0 && n == 0)
930 {
931 if (w == 0)
932 w = 1;
933
934 p = write_block (w);
935 if (p == NULL)
936 return;
937
938 memset (p, ' ', w);
939 goto done;
940 }
941
942 q = conv (n);
943 digits = strlen (q);
944
945 /* Select a width if none was specified. The idea here is to always
946 print something. */
947
948 if (w == 0)
949 w = ((digits < m) ? m : digits);
950
951 p = write_block (w);
952 if (p == NULL)
953 return;
954
955 nzero = 0;
956 if (digits < m)
957 nzero = m - digits;
958
959 /* See if things will work. */
960
961 nblank = w - (nzero + digits);
962
963 if (nblank < 0)
964 {
965 star_fill (p, w);
966 goto done;
967 }
968
969
970 if (!no_leading_blank)
971 {
972 memset (p, ' ', nblank);
973 p += nblank;
974 memset (p, '0', nzero);
975 p += nzero;
976 memcpy (p, q, digits);
977 }
978 else
979 {
980 memset (p, '0', nzero);
981 p += nzero;
982 memcpy (p, q, digits);
983 p += digits;
984 memset (p, ' ', nblank);
985 no_leading_blank = 0;
986 }
987
988 done:
989 return;
990 }
991
992 static void
993 write_decimal (fnode *f, const char *source, int len,
994 char *(*conv) (GFC_INTEGER_LARGEST))
995 {
996 GFC_INTEGER_LARGEST n = 0;
997 int w, m, digits, nsign, nzero, nblank;
998 char *p, *q;
999 sign_t sign;
1000
1001 w = f->u.integer.w;
1002 m = f->u.integer.m;
1003
1004 n = extract_int (source, len);
1005
1006 /* Special case: */
1007
1008 if (m == 0 && n == 0)
1009 {
1010 if (w == 0)
1011 w = 1;
1012
1013 p = write_block (w);
1014 if (p == NULL)
1015 return;
1016
1017 memset (p, ' ', w);
1018 goto done;
1019 }
1020
1021 sign = calculate_sign (n < 0);
1022 if (n < 0)
1023 n = -n;
1024
1025 nsign = sign == SIGN_NONE ? 0 : 1;
1026 q = conv (n);
1027
1028 digits = strlen (q);
1029
1030 /* Select a width if none was specified. The idea here is to always
1031 print something. */
1032
1033 if (w == 0)
1034 w = ((digits < m) ? m : digits) + nsign;
1035
1036 p = write_block (w);
1037 if (p == NULL)
1038 return;
1039
1040 nzero = 0;
1041 if (digits < m)
1042 nzero = m - digits;
1043
1044 /* See if things will work. */
1045
1046 nblank = w - (nsign + nzero + digits);
1047
1048 if (nblank < 0)
1049 {
1050 star_fill (p, w);
1051 goto done;
1052 }
1053
1054 memset (p, ' ', nblank);
1055 p += nblank;
1056
1057 switch (sign)
1058 {
1059 case SIGN_PLUS:
1060 *p++ = '+';
1061 break;
1062 case SIGN_MINUS:
1063 *p++ = '-';
1064 break;
1065 case SIGN_NONE:
1066 break;
1067 }
1068
1069 memset (p, '0', nzero);
1070 p += nzero;
1071
1072 memcpy (p, q, digits);
1073
1074 done:
1075 return;
1076 }
1077
1078
1079 /* Convert unsigned octal to ascii. */
1080
1081 static char *
1082 otoa (GFC_UINTEGER_LARGEST n)
1083 {
1084 char *p;
1085
1086 if (n == 0)
1087 {
1088 scratch[0] = '0';
1089 scratch[1] = '\0';
1090 return scratch;
1091 }
1092
1093 p = scratch + SCRATCH_SIZE - 1;
1094 *p-- = '\0';
1095
1096 while (n != 0)
1097 {
1098 *p = '0' + (n & 7);
1099 p--;
1100 n >>= 3;
1101 }
1102
1103 return ++p;
1104 }
1105
1106
1107 /* Convert unsigned binary to ascii. */
1108
1109 static char *
1110 btoa (GFC_UINTEGER_LARGEST n)
1111 {
1112 char *p;
1113
1114 if (n == 0)
1115 {
1116 scratch[0] = '0';
1117 scratch[1] = '\0';
1118 return scratch;
1119 }
1120
1121 p = scratch + SCRATCH_SIZE - 1;
1122 *p-- = '\0';
1123
1124 while (n != 0)
1125 {
1126 *p-- = '0' + (n & 1);
1127 n >>= 1;
1128 }
1129
1130 return ++p;
1131 }
1132
1133
1134 void
1135 write_i (fnode * f, const char *p, int len)
1136 {
1137 write_decimal (f, p, len, (void *) gfc_itoa);
1138 }
1139
1140
1141 void
1142 write_b (fnode * f, const char *p, int len)
1143 {
1144 write_int (f, p, len, btoa);
1145 }
1146
1147
1148 void
1149 write_o (fnode * f, const char *p, int len)
1150 {
1151 write_int (f, p, len, otoa);
1152 }
1153
1154 void
1155 write_z (fnode * f, const char *p, int len)
1156 {
1157 write_int (f, p, len, xtoa);
1158 }
1159
1160
1161 void
1162 write_d (fnode *f, const char *p, int len)
1163 {
1164 write_float (f, p, len);
1165 }
1166
1167
1168 void
1169 write_e (fnode *f, const char *p, int len)
1170 {
1171 write_float (f, p, len);
1172 }
1173
1174
1175 void
1176 write_f (fnode *f, const char *p, int len)
1177 {
1178 write_float (f, p, len);
1179 }
1180
1181
1182 void
1183 write_en (fnode *f, const char *p, int len)
1184 {
1185 write_float (f, p, len);
1186 }
1187
1188
1189 void
1190 write_es (fnode *f, const char *p, int len)
1191 {
1192 write_float (f, p, len);
1193 }
1194
1195
1196 /* Take care of the X/TR descriptor. */
1197
1198 void
1199 write_x (int len, int nspaces)
1200 {
1201 char *p;
1202
1203 p = write_block (len);
1204 if (p == NULL)
1205 return;
1206
1207 if (nspaces > 0)
1208 memset (&p[len - nspaces], ' ', nspaces);
1209 }
1210
1211
1212 /* List-directed writing. */
1213
1214
1215 /* Write a single character to the output. Returns nonzero if
1216 something goes wrong. */
1217
1218 static int
1219 write_char (char c)
1220 {
1221 char *p;
1222
1223 p = write_block (1);
1224 if (p == NULL)
1225 return 1;
1226
1227 *p = c;
1228
1229 return 0;
1230 }
1231
1232
1233 /* Write a list-directed logical value. */
1234
1235 static void
1236 write_logical (const char *source, int length)
1237 {
1238 write_char (extract_int (source, length) ? 'T' : 'F');
1239 }
1240
1241
1242 /* Write a list-directed integer value. */
1243
1244 static void
1245 write_integer (const char *source, int length)
1246 {
1247 char *p;
1248 const char *q;
1249 int digits;
1250 int width;
1251
1252 q = gfc_itoa (extract_int (source, length));
1253
1254 switch (length)
1255 {
1256 case 1:
1257 width = 4;
1258 break;
1259
1260 case 2:
1261 width = 6;
1262 break;
1263
1264 case 4:
1265 width = 11;
1266 break;
1267
1268 case 8:
1269 width = 20;
1270 break;
1271
1272 default:
1273 width = 0;
1274 break;
1275 }
1276
1277 digits = strlen (q);
1278
1279 if(width < digits )
1280 width = digits ;
1281 p = write_block (width) ;
1282 if (no_leading_blank)
1283 {
1284 memcpy (p, q, digits);
1285 memset(p + digits ,' ', width - digits) ;
1286 }
1287 else
1288 {
1289 memset(p ,' ', width - digits) ;
1290 memcpy (p + width - digits, q, digits);
1291 }
1292 }
1293
1294
1295 /* Write a list-directed string. We have to worry about delimiting
1296 the strings if the file has been opened in that mode. */
1297
1298 static void
1299 write_character (const char *source, int length)
1300 {
1301 int i, extra;
1302 char *p, d;
1303
1304 switch (current_unit->flags.delim)
1305 {
1306 case DELIM_APOSTROPHE:
1307 d = '\'';
1308 break;
1309 case DELIM_QUOTE:
1310 d = '"';
1311 break;
1312 default:
1313 d = ' ';
1314 break;
1315 }
1316
1317 if (d == ' ')
1318 extra = 0;
1319 else
1320 {
1321 extra = 2;
1322
1323 for (i = 0; i < length; i++)
1324 if (source[i] == d)
1325 extra++;
1326 }
1327
1328 p = write_block (length + extra);
1329 if (p == NULL)
1330 return;
1331
1332 if (d == ' ')
1333 memcpy (p, source, length);
1334 else
1335 {
1336 *p++ = d;
1337
1338 for (i = 0; i < length; i++)
1339 {
1340 *p++ = source[i];
1341 if (source[i] == d)
1342 *p++ = d;
1343 }
1344
1345 *p = d;
1346 }
1347 }
1348
1349
1350 /* Output a real number with default format.
1351 This is 1PG14.7E2 for REAL(4), 1PG23.15E3 for REAL(8),
1352 1PG24.15E4 for REAL(10) and 1PG40.31E4 for REAL(16). */
1353
1354 static void
1355 write_real (const char *source, int length)
1356 {
1357 fnode f ;
1358 int org_scale = g.scale_factor;
1359 f.format = FMT_G;
1360 g.scale_factor = 1;
1361 switch (length)
1362 {
1363 case 4:
1364 f.u.real.w = 14;
1365 f.u.real.d = 7;
1366 f.u.real.e = 2;
1367 break;
1368 case 8:
1369 f.u.real.w = 23;
1370 f.u.real.d = 15;
1371 f.u.real.e = 3;
1372 break;
1373 case 10:
1374 f.u.real.w = 24;
1375 f.u.real.d = 15;
1376 f.u.real.e = 4;
1377 break;
1378 case 16:
1379 f.u.real.w = 40;
1380 f.u.real.d = 31;
1381 f.u.real.e = 4;
1382 break;
1383 default:
1384 internal_error ("bad real kind");
1385 break;
1386 }
1387 write_float (&f, source , length);
1388 g.scale_factor = org_scale;
1389 }
1390
1391
1392 static void
1393 write_complex (const char *source, int len)
1394 {
1395 if (write_char ('('))
1396 return;
1397 write_real (source, len);
1398
1399 if (write_char (','))
1400 return;
1401 write_real (source + len, len);
1402
1403 write_char (')');
1404 }
1405
1406
1407 /* Write the separator between items. */
1408
1409 static void
1410 write_separator (void)
1411 {
1412 char *p;
1413
1414 p = write_block (options.separator_len);
1415 if (p == NULL)
1416 return;
1417
1418 memcpy (p, options.separator, options.separator_len);
1419 }
1420
1421
1422 /* Write an item with list formatting.
1423 TODO: handle skipping to the next record correctly, particularly
1424 with strings. */
1425
1426 static void
1427 list_formatted_write_scalar (bt type, void *p, int len)
1428 {
1429 static int char_flag;
1430
1431 if (current_unit == NULL)
1432 return;
1433
1434 if (g.first_item)
1435 {
1436 g.first_item = 0;
1437 char_flag = 0;
1438 write_char (' ');
1439 }
1440 else
1441 {
1442 if (type != BT_CHARACTER || !char_flag ||
1443 current_unit->flags.delim != DELIM_NONE)
1444 write_separator ();
1445 }
1446
1447 switch (type)
1448 {
1449 case BT_INTEGER:
1450 write_integer (p, len);
1451 break;
1452 case BT_LOGICAL:
1453 write_logical (p, len);
1454 break;
1455 case BT_CHARACTER:
1456 write_character (p, len);
1457 break;
1458 case BT_REAL:
1459 write_real (p, len);
1460 break;
1461 case BT_COMPLEX:
1462 write_complex (p, len);
1463 break;
1464 default:
1465 internal_error ("list_formatted_write(): Bad type");
1466 }
1467
1468 char_flag = (type == BT_CHARACTER);
1469 }
1470
1471
1472 void
1473 list_formatted_write (bt type, void *p, int len, size_t nelems)
1474 {
1475 size_t elem;
1476 int size;
1477 char *tmp;
1478
1479 tmp = (char *) p;
1480
1481 if (type == BT_COMPLEX)
1482 size = 2 * len;
1483 else
1484 size = len;
1485
1486 /* Big loop over all the elements. */
1487 for (elem = 0; elem < nelems; elem++)
1488 {
1489 g.item_count++;
1490 list_formatted_write_scalar (type, tmp + size*elem, len);
1491 }
1492 }
1493
1494 /* NAMELIST OUTPUT
1495
1496 nml_write_obj writes a namelist object to the output stream. It is called
1497 recursively for derived type components:
1498 obj = is the namelist_info for the current object.
1499 offset = the offset relative to the address held by the object for
1500 derived type arrays.
1501 base = is the namelist_info of the derived type, when obj is a
1502 component.
1503 base_name = the full name for a derived type, including qualifiers
1504 if any.
1505 The returned value is a pointer to the object beyond the last one
1506 accessed, including nested derived types. Notice that the namelist is
1507 a linear linked list of objects, including derived types and their
1508 components. A tree, of sorts, is implied by the compound names of
1509 the derived type components and this is how this function recurses through
1510 the list. */
1511
1512 /* A generous estimate of the number of characters needed to print
1513 repeat counts and indices, including commas, asterices and brackets. */
1514
1515 #define NML_DIGITS 20
1516
1517 /* Stores the delimiter to be used for character objects. */
1518
1519 static const char * nml_delim;
1520
1521 static namelist_info *
1522 nml_write_obj (namelist_info * obj, index_type offset,
1523 namelist_info * base, char * base_name)
1524 {
1525 int rep_ctr;
1526 int num;
1527 int nml_carry;
1528 index_type len;
1529 index_type obj_size;
1530 index_type nelem;
1531 index_type dim_i;
1532 index_type clen;
1533 index_type elem_ctr;
1534 index_type obj_name_len;
1535 void * p ;
1536 char cup;
1537 char * obj_name;
1538 char * ext_name;
1539 char rep_buff[NML_DIGITS];
1540 namelist_info * cmp;
1541 namelist_info * retval = obj->next;
1542
1543 /* Write namelist variable names in upper case. If a derived type,
1544 nothing is output. If a component, base and base_name are set. */
1545
1546 if (obj->type != GFC_DTYPE_DERIVED)
1547 {
1548 write_character ("\n ", 2);
1549 len = 0;
1550 if (base)
1551 {
1552 len =strlen (base->var_name);
1553 for (dim_i = 0; dim_i < (index_type) strlen (base_name); dim_i++)
1554 {
1555 cup = toupper (base_name[dim_i]);
1556 write_character (&cup, 1);
1557 }
1558 }
1559 for (dim_i =len; dim_i < (index_type) strlen (obj->var_name); dim_i++)
1560 {
1561 cup = toupper (obj->var_name[dim_i]);
1562 write_character (&cup, 1);
1563 }
1564 write_character ("=", 1);
1565 }
1566
1567 /* Counts the number of data output on a line, including names. */
1568
1569 num = 1;
1570
1571 len = obj->len;
1572 obj_size = len;
1573 if (obj->type == GFC_DTYPE_COMPLEX)
1574 obj_size = 2*len;
1575 if (obj->type == GFC_DTYPE_CHARACTER)
1576 obj_size = obj->string_length;
1577 if (obj->var_rank)
1578 obj_size = obj->size;
1579
1580 /* Set the index vector and count the number of elements. */
1581
1582 nelem = 1;
1583 for (dim_i=0; dim_i < obj->var_rank; dim_i++)
1584 {
1585 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1586 nelem = nelem * (obj->dim[dim_i].ubound + 1 - obj->dim[dim_i].lbound);
1587 }
1588
1589 /* Main loop to output the data held in the object. */
1590
1591 rep_ctr = 1;
1592 for (elem_ctr = 0; elem_ctr < nelem; elem_ctr++)
1593 {
1594
1595 /* Build the pointer to the data value. The offset is passed by
1596 recursive calls to this function for arrays of derived types.
1597 Is NULL otherwise. */
1598
1599 p = (void *)(obj->mem_pos + elem_ctr * obj_size);
1600 p += offset;
1601
1602 /* Check for repeat counts of intrinsic types. */
1603
1604 if ((elem_ctr < (nelem - 1)) &&
1605 (obj->type != GFC_DTYPE_DERIVED) &&
1606 !memcmp (p, (void*)(p + obj_size ), obj_size ))
1607 {
1608 rep_ctr++;
1609 }
1610
1611 /* Execute a repeated output. Note the flag no_leading_blank that
1612 is used in the functions used to output the intrinsic types. */
1613
1614 else
1615 {
1616 if (rep_ctr > 1)
1617 {
1618 st_sprintf(rep_buff, " %d*", rep_ctr);
1619 write_character (rep_buff, strlen (rep_buff));
1620 no_leading_blank = 1;
1621 }
1622 num++;
1623
1624 /* Output the data, if an intrinsic type, or recurse into this
1625 routine to treat derived types. */
1626
1627 switch (obj->type)
1628 {
1629
1630 case GFC_DTYPE_INTEGER:
1631 write_integer (p, len);
1632 break;
1633
1634 case GFC_DTYPE_LOGICAL:
1635 write_logical (p, len);
1636 break;
1637
1638 case GFC_DTYPE_CHARACTER:
1639 if (nml_delim)
1640 write_character (nml_delim, 1);
1641 write_character (p, obj->string_length);
1642 if (nml_delim)
1643 write_character (nml_delim, 1);
1644 break;
1645
1646 case GFC_DTYPE_REAL:
1647 write_real (p, len);
1648 break;
1649
1650 case GFC_DTYPE_COMPLEX:
1651 no_leading_blank = 0;
1652 num++;
1653 write_complex (p, len);
1654 break;
1655
1656 case GFC_DTYPE_DERIVED:
1657
1658 /* To treat a derived type, we need to build two strings:
1659 ext_name = the name, including qualifiers that prepends
1660 component names in the output - passed to
1661 nml_write_obj.
1662 obj_name = the derived type name with no qualifiers but %
1663 appended. This is used to identify the
1664 components. */
1665
1666 /* First ext_name => get length of all possible components */
1667
1668 ext_name = (char*)get_mem ( (base_name ? strlen (base_name) : 0)
1669 + (base ? strlen (base->var_name) : 0)
1670 + strlen (obj->var_name)
1671 + obj->var_rank * NML_DIGITS
1672 + 1);
1673
1674 strcpy(ext_name, base_name ? base_name : "");
1675 clen = base ? strlen (base->var_name) : 0;
1676 strcat (ext_name, obj->var_name + clen);
1677
1678 /* Append the qualifier. */
1679
1680 for (dim_i = 0; dim_i < obj->var_rank; dim_i++)
1681 {
1682 strcat (ext_name, dim_i ? "" : "(");
1683 clen = strlen (ext_name);
1684 st_sprintf (ext_name + clen, "%d", (int) obj->ls[dim_i].idx);
1685 strcat (ext_name, (dim_i == obj->var_rank - 1) ? ")" : ",");
1686 }
1687
1688 /* Now obj_name. */
1689
1690 obj_name_len = strlen (obj->var_name) + 1;
1691 obj_name = get_mem (obj_name_len+1);
1692 strcpy (obj_name, obj->var_name);
1693 strcat (obj_name, "%");
1694
1695 /* Now loop over the components. Update the component pointer
1696 with the return value from nml_write_obj => this loop jumps
1697 past nested derived types. */
1698
1699 for (cmp = obj->next;
1700 cmp && !strncmp (cmp->var_name, obj_name, obj_name_len);
1701 cmp = retval)
1702 {
1703 retval = nml_write_obj (cmp, (index_type)(p - obj->mem_pos),
1704 obj, ext_name);
1705 }
1706
1707 free_mem (obj_name);
1708 free_mem (ext_name);
1709 goto obj_loop;
1710
1711 default:
1712 internal_error ("Bad type for namelist write");
1713 }
1714
1715 /* Reset the leading blank suppression, write a comma and, if 5
1716 values have been output, write a newline and advance to column
1717 2. Reset the repeat counter. */
1718
1719 no_leading_blank = 0;
1720 write_character (",", 1);
1721 if (num > 5)
1722 {
1723 num = 0;
1724 write_character ("\n ", 2);
1725 }
1726 rep_ctr = 1;
1727 }
1728
1729 /* Cycle through and increment the index vector. */
1730
1731 obj_loop:
1732
1733 nml_carry = 1;
1734 for (dim_i = 0; nml_carry && (dim_i < obj->var_rank); dim_i++)
1735 {
1736 obj->ls[dim_i].idx += nml_carry ;
1737 nml_carry = 0;
1738 if (obj->ls[dim_i].idx > (ssize_t)obj->dim[dim_i].ubound)
1739 {
1740 obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
1741 nml_carry = 1;
1742 }
1743 }
1744 }
1745
1746 /* Return a pointer beyond the furthest object accessed. */
1747
1748 return retval;
1749 }
1750
1751 /* This is the entry function for namelist writes. It outputs the name
1752 of the namelist and iterates through the namelist by calls to
1753 nml_write_obj. The call below has dummys in the arguments used in
1754 the treatment of derived types. */
1755
1756 void
1757 namelist_write (void)
1758 {
1759 namelist_info * t1, *t2, *dummy = NULL;
1760 index_type i;
1761 index_type dummy_offset = 0;
1762 char c;
1763 char * dummy_name = NULL;
1764 unit_delim tmp_delim;
1765
1766 /* Set the delimiter for namelist output. */
1767
1768 tmp_delim = current_unit->flags.delim;
1769 current_unit->flags.delim = DELIM_NONE;
1770 switch (tmp_delim)
1771 {
1772 case (DELIM_QUOTE):
1773 nml_delim = "\"";
1774 break;
1775
1776 case (DELIM_APOSTROPHE):
1777 nml_delim = "'";
1778 break;
1779
1780 default:
1781 nml_delim = NULL;
1782 }
1783
1784 write_character ("&",1);
1785
1786 /* Write namelist name in upper case - f95 std. */
1787
1788 for (i = 0 ;i < ioparm.namelist_name_len ;i++ )
1789 {
1790 c = toupper (ioparm.namelist_name[i]);
1791 write_character (&c ,1);
1792 }
1793
1794 if (ionml != NULL)
1795 {
1796 t1 = ionml;
1797 while (t1 != NULL)
1798 {
1799 t2 = t1;
1800 t1 = nml_write_obj (t2, dummy_offset, dummy, dummy_name);
1801 }
1802 }
1803 write_character (" /\n", 4);
1804
1805 /* Recover the original delimiter. */
1806
1807 current_unit->flags.delim = tmp_delim;
1808 }
1809
1810 #undef NML_DIGITS