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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [gas/] [atof-generic.c] - Blame information for rev 13

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 jlechner
/* atof_generic.c - turn a string of digits into a Flonum
2
   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000,
3
   2001, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
4
 
5
   This file is part of GAS, the GNU Assembler.
6
 
7
   GAS 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 3, or (at your option)
10
   any later version.
11
 
12
   GAS is distributed in the hope that it will be useful, but WITHOUT
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15
   License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with GAS; see the file COPYING.  If not, write to the Free
19
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20
   02110-1301, USA.  */
21
 
22
#include "as.h"
23
#include "safe-ctype.h"
24
 
25
#ifndef FALSE
26
#define FALSE (0)
27
#endif
28
#ifndef TRUE
29
#define TRUE  (1)
30
#endif
31
 
32
#ifdef TRACE
33
static void flonum_print (const FLONUM_TYPE *);
34
#endif
35
 
36
#define ASSUME_DECIMAL_MARK_IS_DOT
37
 
38
/***********************************************************************\
39
 *                                                                      *
40
 *      Given a string of decimal digits , with optional decimal        *
41
 *      mark and optional decimal exponent (place value) of the         *
42
 *      lowest_order decimal digit: produce a floating point            *
43
 *      number. The number is 'generic' floating point: our             *
44
 *      caller will encode it for a specific machine architecture.      *
45
 *                                                                      *
46
 *      Assumptions                                                     *
47
 *              uses base (radix) 2                                     *
48
 *              this machine uses 2's complement binary integers        *
49
 *              target flonums use "      "         "       "           *
50
 *              target flonums exponents fit in a long                  *
51
 *                                                                      *
52
 \***********************************************************************/
53
 
54
/*
55
 
56
  Syntax:
57
 
58
  <flonum> ::= <optional-sign> <decimal-number> <optional-exponent>
59
  <optional-sign> ::= '+' | '-' | {empty}
60
  <decimal-number> ::= <integer>
61
  | <integer> <radix-character>
62
  | <integer> <radix-character> <integer>
63
  | <radix-character> <integer>
64
 
65
  <optional-exponent> ::= {empty}
66
  | <exponent-character> <optional-sign> <integer>
67
 
68
  <integer> ::= <digit> | <digit> <integer>
69
  <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
70
  <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"}
71
  <radix-character> ::= {one character from "string_of_decimal_marks"}
72
 
73
  */
74
 
75
int
76
atof_generic (/* return pointer to just AFTER number we read.  */
77
              char **address_of_string_pointer,
78
              /* At most one per number.  */
79
              const char *string_of_decimal_marks,
80
              const char *string_of_decimal_exponent_marks,
81
              FLONUM_TYPE *address_of_generic_floating_point_number)
82
{
83
  int return_value;             /* 0 means OK.  */
84
  char *first_digit;
85
  unsigned int number_of_digits_before_decimal;
86
  unsigned int number_of_digits_after_decimal;
87
  long decimal_exponent;
88
  unsigned int number_of_digits_available;
89
  char digits_sign_char;
90
 
91
  /*
92
   * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
93
   * It would be simpler to modify the string, but we don't; just to be nice
94
   * to caller.
95
   * We need to know how many digits we have, so we can allocate space for
96
   * the digits' value.
97
   */
98
 
99
  char *p;
100
  char c;
101
  int seen_significant_digit;
102
 
103
#ifdef ASSUME_DECIMAL_MARK_IS_DOT
104
  assert (string_of_decimal_marks[0] == '.'
105
          && string_of_decimal_marks[1] == 0);
106
#define IS_DECIMAL_MARK(c)      ((c) == '.')
107
#else
108
#define IS_DECIMAL_MARK(c)      (0 != strchr (string_of_decimal_marks, (c)))
109
#endif
110
 
111
  first_digit = *address_of_string_pointer;
112
  c = *first_digit;
113
 
114
  if (c == '-' || c == '+')
115
    {
116
      digits_sign_char = c;
117
      first_digit++;
118
    }
119
  else
120
    digits_sign_char = '+';
121
 
122
  switch (first_digit[0])
123
    {
124
    case 'n':
125
    case 'N':
126
      if (!strncasecmp ("nan", first_digit, 3))
127
        {
128
          address_of_generic_floating_point_number->sign = 0;
129
          address_of_generic_floating_point_number->exponent = 0;
130
          address_of_generic_floating_point_number->leader =
131
            address_of_generic_floating_point_number->low;
132
          *address_of_string_pointer = first_digit + 3;
133
          return 0;
134
        }
135
      break;
136
 
137
    case 'i':
138
    case 'I':
139
      if (!strncasecmp ("inf", first_digit, 3))
140
        {
141
          address_of_generic_floating_point_number->sign =
142
            digits_sign_char == '+' ? 'P' : 'N';
143
          address_of_generic_floating_point_number->exponent = 0;
144
          address_of_generic_floating_point_number->leader =
145
            address_of_generic_floating_point_number->low;
146
 
147
          first_digit += 3;
148
          if (!strncasecmp ("inity", first_digit, 5))
149
            first_digit += 5;
150
 
151
          *address_of_string_pointer = first_digit;
152
 
153
          return 0;
154
        }
155
      break;
156
    }
157
 
158
  number_of_digits_before_decimal = 0;
159
  number_of_digits_after_decimal = 0;
160
  decimal_exponent = 0;
161
  seen_significant_digit = 0;
162
  for (p = first_digit;
163
       (((c = *p) != '\0')
164
        && (!c || !IS_DECIMAL_MARK (c))
165
        && (!c || !strchr (string_of_decimal_exponent_marks, c)));
166
       p++)
167
    {
168
      if (ISDIGIT (c))
169
        {
170
          if (seen_significant_digit || c > '0')
171
            {
172
              ++number_of_digits_before_decimal;
173
              seen_significant_digit = 1;
174
            }
175
          else
176
            {
177
              first_digit++;
178
            }
179
        }
180
      else
181
        {
182
          break;                /* p -> char after pre-decimal digits.  */
183
        }
184
    }                           /* For each digit before decimal mark.  */
185
 
186
#ifndef OLD_FLOAT_READS
187
  /* Ignore trailing 0's after the decimal point.  The original code here
188
   * (ifdef'd out) does not do this, and numbers like
189
   *    4.29496729600000000000e+09      (2**31)
190
   * come out inexact for some reason related to length of the digit
191
   * string.
192
   */
193
  if (c && IS_DECIMAL_MARK (c))
194
    {
195
      unsigned int zeros = 0;    /* Length of current string of zeros */
196
 
197
      for (p++; (c = *p) && ISDIGIT (c); p++)
198
        {
199
          if (c == '0')
200
            {
201
              zeros++;
202
            }
203
          else
204
            {
205
              number_of_digits_after_decimal += 1 + zeros;
206
              zeros = 0;
207
            }
208
        }
209
    }
210
#else
211
  if (c && IS_DECIMAL_MARK (c))
212
    {
213
      for (p++;
214
           (((c = *p) != '\0')
215
            && (!c || !strchr (string_of_decimal_exponent_marks, c)));
216
           p++)
217
        {
218
          if (ISDIGIT (c))
219
            {
220
              /* This may be retracted below.  */
221
              number_of_digits_after_decimal++;
222
 
223
              if ( /* seen_significant_digit || */ c > '0')
224
                {
225
                  seen_significant_digit = TRUE;
226
                }
227
            }
228
          else
229
            {
230
              if (!seen_significant_digit)
231
                {
232
                  number_of_digits_after_decimal = 0;
233
                }
234
              break;
235
            }
236
        }                       /* For each digit after decimal mark.  */
237
    }
238
 
239
  while (number_of_digits_after_decimal
240
         && first_digit[number_of_digits_before_decimal
241
                        + number_of_digits_after_decimal] == '0')
242
    --number_of_digits_after_decimal;
243
#endif
244
 
245
  if (flag_m68k_mri)
246
    {
247
      while (c == '_')
248
        c = *++p;
249
    }
250
  if (c && strchr (string_of_decimal_exponent_marks, c))
251
    {
252
      char digits_exponent_sign_char;
253
 
254
      c = *++p;
255
      if (flag_m68k_mri)
256
        {
257
          while (c == '_')
258
            c = *++p;
259
        }
260
      if (c && strchr ("+-", c))
261
        {
262
          digits_exponent_sign_char = c;
263
          c = *++p;
264
        }
265
      else
266
        {
267
          digits_exponent_sign_char = '+';
268
        }
269
 
270
      for (; (c); c = *++p)
271
        {
272
          if (ISDIGIT (c))
273
            {
274
              decimal_exponent = decimal_exponent * 10 + c - '0';
275
              /*
276
               * BUG! If we overflow here, we lose!
277
               */
278
            }
279
          else
280
            {
281
              break;
282
            }
283
        }
284
 
285
      if (digits_exponent_sign_char == '-')
286
        {
287
          decimal_exponent = -decimal_exponent;
288
        }
289
    }
290
 
291
  *address_of_string_pointer = p;
292
 
293
  number_of_digits_available =
294
    number_of_digits_before_decimal + number_of_digits_after_decimal;
295
  return_value = 0;
296
  if (number_of_digits_available == 0)
297
    {
298
      address_of_generic_floating_point_number->exponent = 0;    /* Not strictly necessary */
299
      address_of_generic_floating_point_number->leader
300
        = -1 + address_of_generic_floating_point_number->low;
301
      address_of_generic_floating_point_number->sign = digits_sign_char;
302
      /* We have just concocted (+/-)0.0E0 */
303
 
304
    }
305
  else
306
    {
307
      int count;                /* Number of useful digits left to scan.  */
308
 
309
      LITTLENUM_TYPE *digits_binary_low;
310
      unsigned int precision;
311
      unsigned int maximum_useful_digits;
312
      unsigned int number_of_digits_to_use;
313
      unsigned int more_than_enough_bits_for_digits;
314
      unsigned int more_than_enough_littlenums_for_digits;
315
      unsigned int size_of_digits_in_littlenums;
316
      unsigned int size_of_digits_in_chars;
317
      FLONUM_TYPE power_of_10_flonum;
318
      FLONUM_TYPE digits_flonum;
319
 
320
      precision = (address_of_generic_floating_point_number->high
321
                   - address_of_generic_floating_point_number->low
322
                   + 1);        /* Number of destination littlenums.  */
323
 
324
      /* Includes guard bits (two littlenums worth) */
325
      maximum_useful_digits = (((precision - 2))
326
                               * ( (LITTLENUM_NUMBER_OF_BITS))
327
                               * 1000000 / 3321928)
328
        + 2;                    /* 2 :: guard digits.  */
329
 
330
      if (number_of_digits_available > maximum_useful_digits)
331
        {
332
          number_of_digits_to_use = maximum_useful_digits;
333
        }
334
      else
335
        {
336
          number_of_digits_to_use = number_of_digits_available;
337
        }
338
 
339
      /* Cast these to SIGNED LONG first, otherwise, on systems with
340
         LONG wider than INT (such as Alpha OSF/1), unsignedness may
341
         cause unexpected results.  */
342
      decimal_exponent += ((long) number_of_digits_before_decimal
343
                           - (long) number_of_digits_to_use);
344
 
345
      more_than_enough_bits_for_digits
346
        = (number_of_digits_to_use * 3321928 / 1000000 + 1);
347
 
348
      more_than_enough_littlenums_for_digits
349
        = (more_than_enough_bits_for_digits
350
           / LITTLENUM_NUMBER_OF_BITS)
351
        + 2;
352
 
353
      /* Compute (digits) part. In "12.34E56" this is the "1234" part.
354
         Arithmetic is exact here. If no digits are supplied then this
355
         part is a 0 valued binary integer.  Allocate room to build up
356
         the binary number as littlenums.  We want this memory to
357
         disappear when we leave this function.  Assume no alignment
358
         problems => (room for n objects) == n * (room for 1
359
         object).  */
360
 
361
      size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
362
      size_of_digits_in_chars = size_of_digits_in_littlenums
363
        * sizeof (LITTLENUM_TYPE);
364
 
365
      digits_binary_low = (LITTLENUM_TYPE *)
366
        alloca (size_of_digits_in_chars);
367
 
368
      memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars);
369
 
370
      /* Digits_binary_low[] is allocated and zeroed.  */
371
 
372
      /*
373
       * Parse the decimal digits as if * digits_low was in the units position.
374
       * Emit a binary number into digits_binary_low[].
375
       *
376
       * Use a large-precision version of:
377
       * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
378
       */
379
 
380
      for (p = first_digit, count = number_of_digits_to_use; count; p++, --count)
381
        {
382
          c = *p;
383
          if (ISDIGIT (c))
384
            {
385
              /*
386
               * Multiply by 10. Assume can never overflow.
387
               * Add this digit to digits_binary_low[].
388
               */
389
 
390
              long carry;
391
              LITTLENUM_TYPE *littlenum_pointer;
392
              LITTLENUM_TYPE *littlenum_limit;
393
 
394
              littlenum_limit = digits_binary_low
395
                + more_than_enough_littlenums_for_digits
396
                - 1;
397
 
398
              carry = c - '0';  /* char -> binary */
399
 
400
              for (littlenum_pointer = digits_binary_low;
401
                   littlenum_pointer <= littlenum_limit;
402
                   littlenum_pointer++)
403
                {
404
                  long work;
405
 
406
                  work = carry + 10 * (long) (*littlenum_pointer);
407
                  *littlenum_pointer = work & LITTLENUM_MASK;
408
                  carry = work >> LITTLENUM_NUMBER_OF_BITS;
409
                }
410
 
411
              if (carry != 0)
412
                {
413
                  /*
414
                   * We have a GROSS internal error.
415
                   * This should never happen.
416
                   */
417
                  as_fatal (_("failed sanity check"));
418
                }
419
            }
420
          else
421
            {
422
              ++count;          /* '.' doesn't alter digits used count.  */
423
            }
424
        }
425
 
426
      /*
427
       * Digits_binary_low[] properly encodes the value of the digits.
428
       * Forget about any high-order littlenums that are 0.
429
       */
430
      while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0
431
             && size_of_digits_in_littlenums >= 2)
432
        size_of_digits_in_littlenums--;
433
 
434
      digits_flonum.low = digits_binary_low;
435
      digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1;
436
      digits_flonum.leader = digits_flonum.high;
437
      digits_flonum.exponent = 0;
438
      /*
439
       * The value of digits_flonum . sign should not be important.
440
       * We have already decided the output's sign.
441
       * We trust that the sign won't influence the other parts of the number!
442
       * So we give it a value for these reasons:
443
       * (1) courtesy to humans reading/debugging
444
       *     these numbers so they don't get excited about strange values
445
       * (2) in future there may be more meaning attached to sign,
446
       *     and what was
447
       *     harmless noise may become disruptive, ill-conditioned (or worse)
448
       *     input.
449
       */
450
      digits_flonum.sign = '+';
451
 
452
      {
453
        /*
454
         * Compute the mantssa (& exponent) of the power of 10.
455
         * If successful, then multiply the power of 10 by the digits
456
         * giving return_binary_mantissa and return_binary_exponent.
457
         */
458
 
459
        LITTLENUM_TYPE *power_binary_low;
460
        int decimal_exponent_is_negative;
461
        /* This refers to the "-56" in "12.34E-56".  */
462
        /* FALSE: decimal_exponent is positive (or 0) */
463
        /* TRUE:  decimal_exponent is negative */
464
        FLONUM_TYPE temporary_flonum;
465
        LITTLENUM_TYPE *temporary_binary_low;
466
        unsigned int size_of_power_in_littlenums;
467
        unsigned int size_of_power_in_chars;
468
 
469
        size_of_power_in_littlenums = precision;
470
        /* Precision has a built-in fudge factor so we get a few guard bits.  */
471
 
472
        decimal_exponent_is_negative = decimal_exponent < 0;
473
        if (decimal_exponent_is_negative)
474
          {
475
            decimal_exponent = -decimal_exponent;
476
          }
477
 
478
        /* From now on: the decimal exponent is > 0. Its sign is separate.  */
479
 
480
        size_of_power_in_chars = size_of_power_in_littlenums
481
          * sizeof (LITTLENUM_TYPE) + 2;
482
 
483
        power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
484
        temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
485
        memset ((char *) power_binary_low, '\0', size_of_power_in_chars);
486
        *power_binary_low = 1;
487
        power_of_10_flonum.exponent = 0;
488
        power_of_10_flonum.low = power_binary_low;
489
        power_of_10_flonum.leader = power_binary_low;
490
        power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1;
491
        power_of_10_flonum.sign = '+';
492
        temporary_flonum.low = temporary_binary_low;
493
        temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1;
494
        /*
495
         * (power) == 1.
496
         * Space for temporary_flonum allocated.
497
         */
498
 
499
        /*
500
         * ...
501
         *
502
         * WHILE        more bits
503
         * DO   find next bit (with place value)
504
         *      multiply into power mantissa
505
         * OD
506
         */
507
        {
508
          int place_number_limit;
509
          /* Any 10^(2^n) whose "n" exceeds this */
510
          /* value will fall off the end of */
511
          /* flonum_XXXX_powers_of_ten[].  */
512
          int place_number;
513
          const FLONUM_TYPE *multiplicand;      /* -> 10^(2^n) */
514
 
515
          place_number_limit = table_size_of_flonum_powers_of_ten;
516
 
517
          multiplicand = (decimal_exponent_is_negative
518
                          ? flonum_negative_powers_of_ten
519
                          : flonum_positive_powers_of_ten);
520
 
521
          for (place_number = 1;/* Place value of this bit of exponent.  */
522
               decimal_exponent;/* Quit when no more 1 bits in exponent.  */
523
               decimal_exponent >>= 1, place_number++)
524
            {
525
              if (decimal_exponent & 1)
526
                {
527
                  if (place_number > place_number_limit)
528
                    {
529
                      /* The decimal exponent has a magnitude so great
530
                         that our tables can't help us fragment it.
531
                         Although this routine is in error because it
532
                         can't imagine a number that big, signal an
533
                         error as if it is the user's fault for
534
                         presenting such a big number.  */
535
                      return_value = ERROR_EXPONENT_OVERFLOW;
536
                      /* quit out of loop gracefully */
537
                      decimal_exponent = 0;
538
                    }
539
                  else
540
                    {
541
#ifdef TRACE
542
                      printf ("before multiply, place_number = %d., power_of_10_flonum:\n",
543
                              place_number);
544
 
545
                      flonum_print (&power_of_10_flonum);
546
                      (void) putchar ('\n');
547
#endif
548
#ifdef TRACE
549
                      printf ("multiplier:\n");
550
                      flonum_print (multiplicand + place_number);
551
                      (void) putchar ('\n');
552
#endif
553
                      flonum_multip (multiplicand + place_number,
554
                                     &power_of_10_flonum, &temporary_flonum);
555
#ifdef TRACE
556
                      printf ("after multiply:\n");
557
                      flonum_print (&temporary_flonum);
558
                      (void) putchar ('\n');
559
#endif
560
                      flonum_copy (&temporary_flonum, &power_of_10_flonum);
561
#ifdef TRACE
562
                      printf ("after copy:\n");
563
                      flonum_print (&power_of_10_flonum);
564
                      (void) putchar ('\n');
565
#endif
566
                    } /* If this bit of decimal_exponent was computable.*/
567
                } /* If this bit of decimal_exponent was set.  */
568
            } /* For each bit of binary representation of exponent */
569
#ifdef TRACE
570
          printf ("after computing power_of_10_flonum:\n");
571
          flonum_print (&power_of_10_flonum);
572
          (void) putchar ('\n');
573
#endif
574
        }
575
 
576
      }
577
 
578
      /*
579
       * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
580
       * It may be the number 1, in which case we don't NEED to multiply.
581
       *
582
       * Multiply (decimal digits) by power_of_10_flonum.
583
       */
584
 
585
      flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number);
586
      /* Assert sign of the number we made is '+'.  */
587
      address_of_generic_floating_point_number->sign = digits_sign_char;
588
 
589
    }
590
  return return_value;
591
}
592
 
593
#ifdef TRACE
594
static void
595
flonum_print (f)
596
     const FLONUM_TYPE *f;
597
{
598
  LITTLENUM_TYPE *lp;
599
  char littlenum_format[10];
600
  sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2);
601
#define print_littlenum(LP)     (printf (littlenum_format, LP))
602
  printf ("flonum @%p %c e%ld", f, f->sign, f->exponent);
603
  if (f->low < f->high)
604
    for (lp = f->high; lp >= f->low; lp--)
605
      print_littlenum (*lp);
606
  else
607
    for (lp = f->low; lp <= f->high; lp++)
608
      print_littlenum (*lp);
609
  printf ("\n");
610
  fflush (stdout);
611
}
612
#endif
613
 
614
/* end of atof_generic.c */

powered by: WebSVN 2.1.0

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