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