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