OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libgfortran/] [io/] [write.c] - Blame information for rev 14

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.