Merge from the pain train
[official-gcc.git] / libgfortran / io / write.c
blob19744d294c0a52c956caa6555f7661a500b5e2e9
1 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
4 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6 Libgfortran is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file. (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
18 executable.)
20 Libgfortran is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with Libgfortran; see the file COPYING. If not, write to
27 the Free Software Foundation, 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA. */
30 #include "config.h"
31 #include <string.h>
32 #include <float.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include "libgfortran.h"
36 #include "io.h"
39 #define star_fill(p, n) memset(p, '*', n)
42 typedef enum
43 { SIGN_NONE, SIGN_MINUS, SIGN_PLUS }
44 sign_t;
47 void
48 write_a (fnode * f, const char *source, int len)
50 int wlen;
51 char *p;
53 wlen = f->u.string.length < 0 ? len : f->u.string.length;
55 p = write_block (wlen);
56 if (p == NULL)
57 return;
59 if (wlen < len)
60 memcpy (p, source, wlen);
61 else
63 memset (p, ' ', wlen - len);
64 memcpy (p + wlen - len, source, len);
68 static int64_t
69 extract_int (const void *p, int len)
71 int64_t i = 0;
73 if (p == NULL)
74 return i;
76 switch (len)
78 case 1:
79 i = *((const int8_t *) p);
80 break;
81 case 2:
82 i = *((const int16_t *) p);
83 break;
84 case 4:
85 i = *((const int32_t *) p);
86 break;
87 case 8:
88 i = *((const int64_t *) p);
89 break;
90 default:
91 internal_error ("bad integer kind");
94 return i;
97 static double
98 extract_real (const void *p, int len)
100 double i = 0.0;
101 switch (len)
103 case 4:
104 i = *((const float *) p);
105 break;
106 case 8:
107 i = *((const double *) p);
108 break;
109 default:
110 internal_error ("bad real kind");
112 return i;
117 /* Given a flag that indicate if a value is negative or not, return a
118 sign_t that gives the sign that we need to produce. */
120 static sign_t
121 calculate_sign (int negative_flag)
123 sign_t s = SIGN_NONE;
125 if (negative_flag)
126 s = SIGN_MINUS;
127 else
128 switch (g.sign_status)
130 case SIGN_SP:
131 s = SIGN_PLUS;
132 break;
133 case SIGN_SS:
134 s = SIGN_NONE;
135 break;
136 case SIGN_S:
137 s = options.optional_plus ? SIGN_PLUS : SIGN_NONE;
138 break;
141 return s;
145 /* Returns the value of 10**d. */
147 static double
148 calculate_exp (int d)
150 int i;
151 double r = 1.0;
153 for (i = 0; i< (d >= 0 ? d : -d); i++)
154 r *= 10;
156 r = (d >= 0) ? r : 1.0 / r;
158 return r;
162 /* Generate corresponding I/O format for FMT_G output.
163 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
164 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
166 Data Magnitude Equivalent Conversion
167 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
168 m = 0 F(w-n).(d-1), n' '
169 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
170 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
171 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
172 ................ ..........
173 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
174 m >= 10**d-0.5 Ew.d[Ee]
176 notes: for Gw.d , n' ' means 4 blanks
177 for Gw.dEe, n' ' means e+2 blanks */
179 static fnode *
180 calculate_G_format (fnode *f, double value, int len, int *num_blank)
182 int e = f->u.real.e;
183 int d = f->u.real.d;
184 int w = f->u.real.w;
185 fnode *newf;
186 double m, exp_d;
187 int low, high, mid;
188 int ubound, lbound;
190 newf = get_mem (sizeof (fnode));
192 /* Absolute value. */
193 m = (value > 0.0) ? value : -value;
195 /* In case of the two data magnitude ranges,
196 generate E editing, Ew.d[Ee]. */
197 exp_d = calculate_exp (d);
198 if ((m > 0.0 && m < 0.1 - 0.05 / (double) exp_d)
199 || (m >= (double) exp_d - 0.5 ))
201 newf->format = FMT_E;
202 newf->u.real.w = w;
203 newf->u.real.d = d;
204 newf->u.real.e = e;
205 *num_blank = 0;
206 return newf;
209 /* Use binary search to find the data magnitude range. */
210 mid = 0;
211 low = 0;
212 high = d + 1;
213 lbound = 0;
214 ubound = d + 1;
216 while (low <= high)
218 double temp;
219 mid = (low + high) / 2;
221 /* 0.1 * 10**mid - 0.5 * 10**(mid-d-1) */
222 temp = 0.1 * calculate_exp (mid) - 0.5 * calculate_exp (mid - d - 1);
224 if (m < temp)
226 ubound = mid;
227 if (ubound == lbound + 1)
228 break;
229 high = mid - 1;
231 else if (m > temp)
233 lbound = mid;
234 if (ubound == lbound + 1)
236 mid ++;
237 break;
239 low = mid + 1;
241 else
242 break;
245 /* Pad with blanks where the exponent would be. */
246 if (e < 0)
247 *num_blank = 4;
248 else
249 *num_blank = e + 2;
251 /* Generate the F editing. F(w-n).(-(mid-d-1)), n' '. */
252 newf->format = FMT_F;
253 newf->u.real.w = f->u.real.w - *num_blank;
255 /* Special case. */
256 if (m == 0.0)
257 newf->u.real.d = d - 1;
258 else
259 newf->u.real.d = - (mid - d - 1);
261 /* For F editing, the scale factor is ignored. */
262 g.scale_factor = 0;
263 return newf;
267 /* Output a real number according to its format which is FMT_G free. */
269 static void
270 output_float (fnode *f, double value, int len)
272 /* This must be large enough to accurately hold any value. */
273 char buffer[32];
274 char *out;
275 char *digits;
276 int e;
277 char expchar;
278 format_token ft;
279 int w;
280 int d;
281 int edigits;
282 int ndigits;
283 /* Number of digits before the decimal point. */
284 int nbefore;
285 /* Number of zeros after the decimal point. */
286 int nzero;
287 /* Number of digits after the decimal point. */
288 int nafter;
289 int leadzero;
290 int nblanks;
291 int i;
292 sign_t sign;
294 ft = f->format;
295 w = f->u.real.w;
296 d = f->u.real.d;
298 /* We should always know the field width and precision. */
299 if (d < 0)
300 internal_error ("Unspecified precision");
302 /* Use sprintf to print the number in the format +D.DDDDe+ddd
303 For an N digit exponent, this gives us (32-6)-N digits after the
304 decimal point, plus another one before the decimal point. */
305 sign = calculate_sign (value < 0.0);
306 if (value < 0)
307 value = -value;
309 /* Printf always prints at least two exponent digits. */
310 if (value == 0)
311 edigits = 2;
312 else
314 edigits = 1 + (int) log10 (fabs(log10 (value)));
315 if (edigits < 2)
316 edigits = 2;
319 if (ft == FMT_F || ft == FMT_EN
320 || ((ft == FMT_D || ft == FMT_E) && g.scale_factor != 0))
322 /* Always convert at full precision to avoid double rounding. */
323 ndigits = 27 - edigits;
325 else
327 /* We know the number of digits, so can let printf do the rounding
328 for us. */
329 if (ft == FMT_ES)
330 ndigits = d + 1;
331 else
332 ndigits = d;
333 if (ndigits > 27 - edigits)
334 ndigits = 27 - edigits;
337 sprintf (buffer, "%+-#31.*e", ndigits - 1, value);
339 /* Check the resulting string has punctuation in the correct places. */
340 if (buffer[2] != '.' || buffer[ndigits + 2] != 'e')
341 internal_error ("printf is broken");
343 /* Read the exponent back in. */
344 e = atoi (&buffer[ndigits + 3]) + 1;
346 /* Make sure zero comes out as 0.0e0. */
347 if (value == 0.0)
348 e = 0;
350 /* Normalize the fractional component. */
351 buffer[2] = buffer[1];
352 digits = &buffer[2];
354 /* Figure out where to place the decimal point. */
355 switch (ft)
357 case FMT_F:
358 nbefore = e + g.scale_factor;
359 if (nbefore < 0)
361 nzero = -nbefore;
362 if (nzero > d)
363 nzero = d;
364 nafter = d - nzero;
365 nbefore = 0;
367 else
369 nzero = 0;
370 nafter = d;
372 expchar = 0;
373 break;
375 case FMT_E:
376 case FMT_D:
377 i = g.scale_factor;
378 e -= i;
379 if (i < 0)
381 nbefore = 0;
382 nzero = -i;
383 nafter = d + i;
385 else if (i > 0)
387 nbefore = i;
388 nzero = 0;
389 nafter = (d - i) + 1;
391 else /* i == 0 */
393 nbefore = 0;
394 nzero = 0;
395 nafter = d;
398 if (ft = FMT_E)
399 expchar = 'E';
400 else
401 expchar = 'D';
402 break;
404 case FMT_EN:
405 /* The exponent must be a multiple of three, with 1-3 digits before
406 the decimal point. */
407 e--;
408 if (e >= 0)
409 nbefore = e % 3;
410 else
412 nbefore = (-e) % 3;
413 if (nbefore != 0)
414 nbefore = 3 - nbefore;
416 e -= nbefore;
417 nbefore++;
418 nzero = 0;
419 nafter = d;
420 expchar = 'E';
421 break;
423 case FMT_ES:
424 e--;
425 nbefore = 1;
426 nzero = 0;
427 nafter = d;
428 expchar = 'E';
429 break;
431 default:
432 /* Should never happen. */
433 internal_error ("Unexpected format token");
436 /* Round the value. */
437 if (nbefore + nafter == 0)
438 ndigits = 0;
439 else if (nbefore + nafter < ndigits)
441 ndigits = nbefore + nafter;
442 i = ndigits;
443 if (digits[i] >= '5')
445 /* Propagate the carry. */
446 for (i--; i >= 0; i--)
448 if (digits[i] != '9')
450 digits[i]++;
451 break;
453 digits[i] = '0';
456 if (i < 0)
458 /* The carry overflowed. Fortunately we have some spare space
459 at the start of the buffer. We may discard some digits, but
460 this is ok because we already know they are zero. */
461 digits--;
462 digits[0] = '1';
463 if (ft == FMT_F)
465 if (nzero > 0)
467 nzero--;
468 nafter++;
470 else
471 nbefore++;
473 else if (ft == FMT_EN)
475 nbefore++;
476 if (nbefore == 4)
478 nbefore = 1;
479 e += 3;
482 else
483 e++;
488 /* Calculate the format of the exponent field. */
489 if (expchar)
491 edigits = 1;
492 for (i = abs (e); i >= 10; i /= 10)
493 edigits++;
495 if (f->u.real.e < 0)
497 /* Width not specified. Must be no more than 3 digits. */
498 if (e > 999 || e < -999)
499 edigits = -1;
500 else
502 edigits = 4;
503 if (e > 99 || e < -99)
504 expchar = ' ';
507 else
509 /* Exponent width specified, check it is wide enough. */
510 if (edigits > f->u.real.e)
511 edigits = -1;
512 else
513 edigits = f->u.real.e + 2;
516 else
517 edigits = 0;
519 /* Pick a field size if none was specified. */
520 if (w <= 0)
521 w = nbefore + nzero + nafter + 2;
523 /* Create the ouput buffer. */
524 out = write_block (w);
525 if (out == NULL)
526 return;
528 /* Zero values always output as positive, even if the value was negative
529 before rounding. */
530 for (i = 0; i < ndigits; i++)
532 if (digits[i] != '0')
533 break;
535 if (i == ndigits)
536 sign = calculate_sign (0);
538 /* Work out how much padding is needed. */
539 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
540 if (sign != SIGN_NONE)
541 nblanks--;
543 /* Check the value fits in the specified field width. */
544 if (nblanks < 0 || edigits == -1)
546 star_fill (out, w);
547 return;
550 /* See if we have space for a zero before the decimal point. */
551 if (nbefore == 0 && nblanks > 0)
553 leadzero = 1;
554 nblanks--;
556 else
557 leadzero = 0;
559 /* Padd to full field width. */
560 if (nblanks > 0)
562 memset (out, ' ', nblanks);
563 out += nblanks;
566 /* Output the initial sign (if any). */
567 if (sign == SIGN_PLUS)
568 *(out++) = '+';
569 else if (sign == SIGN_MINUS)
570 *(out++) = '-';
572 /* Output an optional leading zero. */
573 if (leadzero)
574 *(out++) = '0';
576 /* Output the part before the decimal point, padding with zeros. */
577 if (nbefore > 0)
579 if (nbefore > ndigits)
580 i = ndigits;
581 else
582 i = nbefore;
584 memcpy (out, digits, i);
585 while (i < nbefore)
586 out[i++] = '0';
588 digits += i;
589 ndigits -= i;
590 out += nbefore;
592 /* Output the decimal point. */
593 *(out++) = '.';
595 /* Output leading zeros after the decimal point. */
596 if (nzero > 0)
598 for (i = 0; i < nzero; i++)
599 *(out++) = '0';
602 /* Output digits after the decimal point, padding with zeros. */
603 if (nafter > 0)
605 if (nafter > ndigits)
606 i = ndigits;
607 else
608 i = nafter;
610 memcpy (out, digits, i);
611 while (i < nafter)
612 out[i++] = '0';
614 digits += i;
615 ndigits -= i;
616 out += nafter;
619 /* Output the exponent. */
620 if (expchar)
622 if (expchar != ' ')
624 *(out++) = expchar;
625 edigits--;
627 #if HAVE_SNPRINTF
628 snprintf (buffer, 32, "%+0*d", edigits, e);
629 #else
630 sprintf (buffer, "%+0*d", edigits, e);
631 #endif
632 memcpy (out, buffer, edigits);
637 void
638 write_l (fnode * f, char *source, int len)
640 char *p;
641 int64_t n;
643 p = write_block (f->u.w);
644 if (p == NULL)
645 return;
647 memset (p, ' ', f->u.w - 1);
648 n = extract_int (source, len);
649 p[f->u.w - 1] = (n) ? 'T' : 'F';
652 /* Output a real number according to its format. */
654 static void
655 write_float (fnode *f, const char *source, int len)
657 double n;
658 int nb =0, res;
659 char * p, fin;
660 fnode *f2 = NULL;
662 n = extract_real (source, len);
664 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
666 res = isfinite (n);
667 if (res == 0)
669 nb = f->u.real.w;
670 p = write_block (nb);
671 if (nb < 3)
673 memset (p, '*',nb);
674 return;
677 memset(p, ' ', nb);
678 res = !isnan (n);
679 if (res != 0)
681 if (signbit(n))
682 fin = '-';
683 else
684 fin = '+';
686 if (nb > 7)
687 memcpy(p + nb - 8, "Infinity", 8);
688 else
689 memcpy(p + nb - 3, "Inf", 3);
690 if (nb < 8 && nb > 3)
691 p[nb - 4] = fin;
692 else if (nb > 8)
693 p[nb - 9] = fin;
695 else
696 memcpy(p + nb - 3, "NaN", 3);
697 return;
701 if (f->format != FMT_G)
703 output_float (f, n, len);
705 else
707 f2 = calculate_G_format(f, n, len, &nb);
708 output_float (f2, n, len);
709 if (f2 != NULL)
710 free_mem(f2);
712 if (nb > 0)
714 p = write_block (nb);
715 memset (p, ' ', nb);
721 static void
722 write_int (fnode *f, const char *source, int len, char *(*conv) (uint64_t))
724 uint32_t ns =0;
725 uint64_t n = 0;
726 int w, m, digits, nzero, nblank;
727 char *p, *q;
729 w = f->u.integer.w;
730 m = f->u.integer.m;
732 n = extract_int (source, len);
734 /* Special case: */
736 if (m == 0 && n == 0)
738 if (w == 0)
739 w = 1;
741 p = write_block (w);
742 if (p == NULL)
743 return;
745 memset (p, ' ', w);
746 goto done;
750 if (len < 8)
752 ns = n;
753 q = conv (ns);
755 else
756 q = conv (n);
758 digits = strlen (q);
760 /* Select a width if none was specified. The idea here is to always
761 print something. */
763 if (w == 0)
764 w = ((digits < m) ? m : digits);
766 p = write_block (w);
767 if (p == NULL)
768 return;
770 nzero = 0;
771 if (digits < m)
772 nzero = m - digits;
774 /* See if things will work. */
776 nblank = w - (nzero + digits);
778 if (nblank < 0)
780 star_fill (p, w);
781 goto done;
784 memset (p, ' ', nblank);
785 p += nblank;
787 memset (p, '0', nzero);
788 p += nzero;
790 memcpy (p, q, digits);
792 done:
793 return;
796 static void
797 write_decimal (fnode *f, const char *source, int len, char *(*conv) (int64_t))
799 int64_t n = 0;
800 int w, m, digits, nsign, nzero, nblank;
801 char *p, *q;
802 sign_t sign;
804 w = f->u.integer.w;
805 m = f->u.integer.m;
807 n = extract_int (source, len);
809 /* Special case: */
811 if (m == 0 && n == 0)
813 if (w == 0)
814 w = 1;
816 p = write_block (w);
817 if (p == NULL)
818 return;
820 memset (p, ' ', w);
821 goto done;
824 sign = calculate_sign (n < 0);
825 if (n < 0)
826 n = -n;
828 nsign = sign == SIGN_NONE ? 0 : 1;
829 q = conv (n);
831 digits = strlen (q);
833 /* Select a width if none was specified. The idea here is to always
834 print something. */
836 if (w == 0)
837 w = ((digits < m) ? m : digits) + nsign;
839 p = write_block (w);
840 if (p == NULL)
841 return;
843 nzero = 0;
844 if (digits < m)
845 nzero = m - digits;
847 /* See if things will work. */
849 nblank = w - (nsign + nzero + digits);
851 if (nblank < 0)
853 star_fill (p, w);
854 goto done;
857 memset (p, ' ', nblank);
858 p += nblank;
860 switch (sign)
862 case SIGN_PLUS:
863 *p++ = '+';
864 break;
865 case SIGN_MINUS:
866 *p++ = '-';
867 break;
868 case SIGN_NONE:
869 break;
872 memset (p, '0', nzero);
873 p += nzero;
875 memcpy (p, q, digits);
877 done:
878 return;
882 /* Convert unsigned octal to ascii. */
884 static char *
885 otoa (uint64_t n)
887 char *p;
889 if (n == 0)
891 scratch[0] = '0';
892 scratch[1] = '\0';
893 return scratch;
896 p = scratch + sizeof (SCRATCH_SIZE) - 1;
897 *p-- = '\0';
899 while (n != 0)
901 *p = '0' + (n & 7);
902 p -- ;
903 n >>= 3;
906 return ++p;
910 /* Convert unsigned binary to ascii. */
912 static char *
913 btoa (uint64_t n)
915 char *p;
917 if (n == 0)
919 scratch[0] = '0';
920 scratch[1] = '\0';
921 return scratch;
924 p = scratch + sizeof (SCRATCH_SIZE) - 1;
925 *p-- = '\0';
927 while (n != 0)
929 *p-- = '0' + (n & 1);
930 n >>= 1;
933 return ++p;
937 void
938 write_i (fnode * f, const char *p, int len)
940 write_decimal (f, p, len, (void *) gfc_itoa);
944 void
945 write_b (fnode * f, const char *p, int len)
947 write_int (f, p, len, btoa);
951 void
952 write_o (fnode * f, const char *p, int len)
954 write_int (f, p, len, otoa);
957 void
958 write_z (fnode * f, const char *p, int len)
960 write_int (f, p, len, xtoa);
964 void
965 write_d (fnode *f, const char *p, int len)
967 write_float (f, p, len);
971 void
972 write_e (fnode *f, const char *p, int len)
974 write_float (f, p, len);
978 void
979 write_f (fnode *f, const char *p, int len)
981 write_float (f, p, len);
985 void
986 write_en (fnode *f, const char *p, int len)
988 write_float (f, p, len);
992 void
993 write_es (fnode *f, const char *p, int len)
995 write_float (f, p, len);
999 /* Take care of the X/TR descriptor. */
1001 void
1002 write_x (fnode * f)
1004 char *p;
1006 p = write_block (f->u.n);
1007 if (p == NULL)
1008 return;
1010 memset (p, ' ', f->u.n);
1014 /* List-directed writing. */
1017 /* Write a single character to the output. Returns nonzero if
1018 something goes wrong. */
1020 static int
1021 write_char (char c)
1023 char *p;
1025 p = write_block (1);
1026 if (p == NULL)
1027 return 1;
1029 *p = c;
1031 return 0;
1035 /* Write a list-directed logical value. */
1037 static void
1038 write_logical (const char *source, int length)
1040 write_char (extract_int (source, length) ? 'T' : 'F');
1044 /* Write a list-directed integer value. */
1046 static void
1047 write_integer (const char *source, int length)
1049 char *p;
1050 const char *q;
1051 int digits;
1052 int width;
1054 q = gfc_itoa (extract_int (source, length));
1056 switch (length)
1058 case 1:
1059 width = 4;
1060 break;
1062 case 2:
1063 width = 6;
1064 break;
1066 case 4:
1067 width = 11;
1068 break;
1070 case 8:
1071 width = 20;
1072 break;
1074 default:
1075 width = 0;
1076 break;
1079 digits = strlen (q);
1081 if(width < digits )
1082 width = digits ;
1083 p = write_block (width) ;
1085 memset(p ,' ', width - digits) ;
1086 memcpy (p + width - digits, q, digits);
1090 /* Write a list-directed string. We have to worry about delimiting
1091 the strings if the file has been opened in that mode. */
1093 static void
1094 write_character (const char *source, int length)
1096 int i, extra;
1097 char *p, d;
1099 switch (current_unit->flags.delim)
1101 case DELIM_APOSTROPHE:
1102 d = '\'';
1103 break;
1104 case DELIM_QUOTE:
1105 d = '"';
1106 break;
1107 default:
1108 d = ' ';
1109 break;
1112 if (d == ' ')
1113 extra = 0;
1114 else
1116 extra = 2;
1118 for (i = 0; i < length; i++)
1119 if (source[i] == d)
1120 extra++;
1123 p = write_block (length + extra);
1124 if (p == NULL)
1125 return;
1127 if (d == ' ')
1128 memcpy (p, source, length);
1129 else
1131 *p++ = d;
1133 for (i = 0; i < length; i++)
1135 *p++ = source[i];
1136 if (source[i] == d)
1137 *p++ = d;
1140 *p = d;
1145 /* Output a real number with default format.
1146 This is 1PG14.7E2 for REAL(4) and 1PG23.15E3 for REAL(8). */
1148 static void
1149 write_real (const char *source, int length)
1151 fnode f ;
1152 int org_scale = g.scale_factor;
1153 f.format = FMT_G;
1154 g.scale_factor = 1;
1155 if (length < 8)
1157 f.u.real.w = 14;
1158 f.u.real.d = 7;
1159 f.u.real.e = 2;
1161 else
1163 f.u.real.w = 23;
1164 f.u.real.d = 15;
1165 f.u.real.e = 3;
1167 write_float (&f, source , length);
1168 g.scale_factor = org_scale;
1172 static void
1173 write_complex (const char *source, int len)
1175 if (write_char ('('))
1176 return;
1177 write_real (source, len);
1179 if (write_char (','))
1180 return;
1181 write_real (source + len, len);
1183 write_char (')');
1187 /* Write the separator between items. */
1189 static void
1190 write_separator (void)
1192 char *p;
1194 p = write_block (options.separator_len);
1195 if (p == NULL)
1196 return;
1198 memcpy (p, options.separator, options.separator_len);
1202 /* Write an item with list formatting.
1203 TODO: handle skipping to the next record correctly, particularly
1204 with strings. */
1206 void
1207 list_formatted_write (bt type, void *p, int len)
1209 static int char_flag;
1211 if (current_unit == NULL)
1212 return;
1214 if (g.first_item)
1216 g.first_item = 0;
1217 char_flag = 0;
1218 write_char (' ');
1220 else
1222 if (type != BT_CHARACTER || !char_flag ||
1223 current_unit->flags.delim != DELIM_NONE)
1224 write_separator ();
1227 switch (type)
1229 case BT_INTEGER:
1230 write_integer (p, len);
1231 break;
1232 case BT_LOGICAL:
1233 write_logical (p, len);
1234 break;
1235 case BT_CHARACTER:
1236 write_character (p, len);
1237 break;
1238 case BT_REAL:
1239 write_real (p, len);
1240 break;
1241 case BT_COMPLEX:
1242 write_complex (p, len);
1243 break;
1244 default:
1245 internal_error ("list_formatted_write(): Bad type");
1248 char_flag = (type == BT_CHARACTER);
1251 void
1252 namelist_write (void)
1254 namelist_info * t1, *t2;
1255 int len,num;
1256 void * p;
1258 num = 0;
1259 write_character("&",1);
1260 write_character (ioparm.namelist_name, ioparm.namelist_name_len);
1261 write_character("\n",1);
1263 if (ionml != NULL)
1265 t1 = ionml;
1266 while (t1 != NULL)
1268 num ++;
1269 t2 = t1;
1270 t1 = t1->next;
1271 if (t2->var_name)
1273 write_character(t2->var_name, strlen(t2->var_name));
1274 write_character("=",1);
1276 len = t2->len;
1277 p = t2->mem_pos;
1278 switch (t2->type)
1280 case BT_INTEGER:
1281 write_integer (p, len);
1282 break;
1283 case BT_LOGICAL:
1284 write_logical (p, len);
1285 break;
1286 case BT_CHARACTER:
1287 write_character (p, t2->string_length);
1288 break;
1289 case BT_REAL:
1290 write_real (p, len);
1291 break;
1292 case BT_COMPLEX:
1293 write_complex (p, len);
1294 break;
1295 default:
1296 internal_error ("Bad type for namelist write");
1298 write_character(",",1);
1299 if (num > 5)
1301 num = 0;
1302 write_character("\n",1);
1306 write_character("/",1);