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