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