Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5222 serge 1
/* 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, 2009 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
   ::=   
59
   ::= '+' | '-' | {empty}
60
   ::= 
61
  |  
62
  |   
63
  |  
64
 
65
   ::= {empty}
66
  |   
67
 
68
   ::=  |  
69
   ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
70
   ::= {one character from "string_of_decimal_exponent_marks"}
71
   ::= {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
  gas_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 */