Subversion Repositories Kolibri OS

Rev

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