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