|
|
1.1.1.2 root 1: /* atof_generic.c - turn a string of digits into a Flonum
2: Copyright (C) 1987 Free Software Foundation, Inc.
1.1 root 3:
1.1.1.2 root 4: This file is part of GAS, the GNU Assembler.
1.1 root 5:
1.1.1.2 root 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 1, or (at your option)
9: any later version.
10:
11: GAS is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public 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
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
1.1 root 19:
20: #include <ctype.h>
21: #include "flonum.h"
1.1.1.2 root 22: #ifdef __GNUC__
23: #define alloca __builtin_alloca
24: #else
1.1 root 25: #ifdef sparc
26: #include <alloca.h>
27: #endif
1.1.1.2 root 28: #endif
29:
30: #ifdef USG
31: #define bzero(s,n) memset(s,0,n)
32: #define index strchr
33: #endif
1.1 root 34:
35: #define FALSE (0)
36: #define TRUE (1)
37:
38: char *index();
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 int *
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: <optional-exponent> ::= {empty} | <exponent-character> <optional-sign> <integer>
67: <integer> ::= <digit> | <digit> <integer>
68: <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
69: <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"}
70: <radix-character> ::= {one character from "string_of_decimal_marks"}
71:
72: */
73:
74: int /* 0 if OK */
75:
76: atof_generic (
77: address_of_string_pointer, /* return pointer to just AFTER number we read. */
78: string_of_decimal_marks, /* At most one per number. */
79: string_of_decimal_exponent_marks,
80: address_of_generic_floating_point_number)
81:
82: char * * address_of_string_pointer;
83: char * string_of_decimal_marks;
84: char * string_of_decimal_exponent_marks;
85: FLONUM_TYPE * address_of_generic_floating_point_number;
86:
87: {
88:
89: int return_value; /* 0 means OK. */
90: char * first_digit;
91: /* char * last_digit; JF unused */
92: int number_of_digits_before_decimal;
93: int number_of_digits_after_decimal;
94: long int decimal_exponent;
95: int number_of_digits_available;
96: char digits_sign_char;
97:
98: {
99: /*
100: * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
101: * It would be simpler to modify the string, but we don't; just to be nice
102: * to caller.
103: * We need to know how many digits we have, so we can allocate space for
104: * the digits' value.
105: */
106:
107: char * p;
108: char c;
109: int seen_significant_digit;
110:
111: first_digit = * address_of_string_pointer;
112: c= *first_digit;
1.1.1.3 ! root 113: if( (c=='n' || c=='N')
! 114: && (first_digit[1]=='a' || first_digit[1]=='A')
! 115: && (first_digit[2]=='n' || first_digit[2]=='N')) {
1.1.1.2 root 116: address_of_generic_floating_point_number->sign=0;
117: address_of_generic_floating_point_number->exponent=0;
118: address_of_generic_floating_point_number->leader=address_of_generic_floating_point_number->low;
119: (*address_of_string_pointer)+=3;
120: return 0;
121: }
1.1.1.3 ! root 122: if( (c=='i' || c=='I')
! 123: && (first_digit[1]=='n' || first_digit[1]=='N')
! 124: && (first_digit[2]=='f' || first_digit[2]=='F')) {
1.1.1.2 root 125: address_of_generic_floating_point_number->sign='P';
126: address_of_generic_floating_point_number->exponent=0;
127: address_of_generic_floating_point_number->leader=address_of_generic_floating_point_number->low;
128: (*address_of_string_pointer)+=3;
129: return 0;
130: }
1.1 root 131: if (c=='-' || c=='+')
132: {
1.1.1.3 ! root 133: if( (first_digit[1]=='i' || first_digit[1]=='I')
! 134: && (first_digit[2]=='n' || first_digit[2]=='N')
! 135: && (first_digit[3]=='f' || first_digit[3]=='F')) {
1.1.1.2 root 136: address_of_generic_floating_point_number->sign = (c=='+') ? 'P' : 'N';
137: address_of_generic_floating_point_number->exponent=0;
138: address_of_generic_floating_point_number->leader=address_of_generic_floating_point_number->low;
139: (*address_of_string_pointer)+=4;
140: return 0;
141: }
1.1 root 142: digits_sign_char = c;
143: first_digit ++;
144: }
145: else
146: {
147: digits_sign_char = '+';
148: }
149: number_of_digits_before_decimal = 0;
150: number_of_digits_after_decimal = 0;
151: decimal_exponent = 0;
152: seen_significant_digit = FALSE;
153: for (p = first_digit;
154: (c = * p)
155: && (!c || ! index (string_of_decimal_marks, c) )
156: && (!c || ! index (string_of_decimal_exponent_marks, c) );
157: p ++)
158: {
159: if (isdigit(c))
160: {
161: if (seen_significant_digit || c > '0')
162: {
163: number_of_digits_before_decimal ++;
164: seen_significant_digit = TRUE;
165: }
166: else
167: {
168: first_digit++;
169: }
170: }
171: else
172: {
173: break; /* p -> char after pre-decimal digits. */
174: }
175: } /* For each digit before decimal mark. */
176: if (c && index (string_of_decimal_marks, c))
177: {
178: for (p ++;
179: (c = * p)
180: && (!c || ! index (string_of_decimal_exponent_marks, c) );
181: p ++)
182: {
183: if (isdigit(c))
184: {
185: number_of_digits_after_decimal ++; /* This may be retracted below. */
186: if (/* seen_significant_digit || */ c > '0')
187: {
188: seen_significant_digit = TRUE;
189: }
190: }
191: else
192: {
193: if ( ! seen_significant_digit)
194: {
195: number_of_digits_after_decimal = 0;
196: }
197: break;
198: }
199: } /* For each digit after decimal mark. */
200: }
1.1.1.3 ! root 201: while(number_of_digits_after_decimal && first_digit[number_of_digits_before_decimal+number_of_digits_after_decimal]=='0')
! 202: --number_of_digits_after_decimal;
1.1 root 203: /* last_digit = p; JF unused */
204:
205: if (c && index (string_of_decimal_exponent_marks, c) )
206: {
207: char digits_exponent_sign_char;
208:
209: c = * ++ p;
210: if (c && index ("+-",c))
211: {
212: digits_exponent_sign_char = c;
213: c = * ++ p;
214: }
215: else
216: {
217: digits_exponent_sign_char = '+';
218: }
219: for (;
220: (c);
221: c = * ++ p)
222: {
223: if (isdigit(c))
224: {
225: decimal_exponent = decimal_exponent * 10 + c - '0';
226: /*
227: * BUG! If we overflow here, we lose!
228: */
229: }
230: else
231: {
232: break;
233: }
234: }
235: if (digits_exponent_sign_char == '-')
236: {
237: decimal_exponent = - decimal_exponent;
238: }
239: }
240: * address_of_string_pointer = p;
241: }
242:
243: number_of_digits_available =
244: number_of_digits_before_decimal
245: + number_of_digits_after_decimal;
246: return_value = 0;
247: if (number_of_digits_available == 0)
248: {
249: address_of_generic_floating_point_number -> exponent = 0; /* Not strictly necessary */
250: address_of_generic_floating_point_number -> leader
251: = -1 + address_of_generic_floating_point_number -> low;
252: address_of_generic_floating_point_number -> sign = digits_sign_char;
253: /* We have just concocted (+/-)0.0E0 */
254: }
255: else
256: {
257: LITTLENUM_TYPE * digits_binary_low;
258: int precision;
259: int maximum_useful_digits;
260: int number_of_digits_to_use;
261: int more_than_enough_bits_for_digits;
262: int more_than_enough_littlenums_for_digits;
263: int size_of_digits_in_littlenums;
264: int size_of_digits_in_chars;
265: FLONUM_TYPE power_of_10_flonum;
266: FLONUM_TYPE digits_flonum;
267:
268:
269: precision = (address_of_generic_floating_point_number -> high
270: - address_of_generic_floating_point_number -> low
271: + 1
1.1.1.3 ! root 272: ); /* Number of destination littlenums. */
! 273: /* Includes guard bits (two littlenums worth) */
1.1 root 274: maximum_useful_digits = ( ((double) (precision - 2))
275: * ((double) (LITTLENUM_NUMBER_OF_BITS))
276: / (LOG_TO_BASE_2_OF_10)
277: )
278: + 2; /* 2 :: guard digits. */
279: if (number_of_digits_available > maximum_useful_digits)
280: {
281: number_of_digits_to_use = maximum_useful_digits;
282: }
283: else
284: {
285: number_of_digits_to_use = number_of_digits_available;
286: }
287: decimal_exponent += number_of_digits_before_decimal - number_of_digits_to_use;
288:
289: more_than_enough_bits_for_digits
290: = ((((double)number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1);
291: more_than_enough_littlenums_for_digits
292: = ( more_than_enough_bits_for_digits
293: / LITTLENUM_NUMBER_OF_BITS
294: )
295: + 2;
296:
297: /*
298: * Compute (digits) part. In "12.34E56" this is the "1234" part.
299: * Arithmetic is exact here. If no digits are supplied then
300: * this part is a 0 valued binary integer.
301: * Allocate room to build up the binary number as littlenums.
302: * We want this memory to disappear when we leave this function.
303: * Assume no alignment problems => (room for n objects) ==
304: * n * (room for 1 object).
305: */
306:
307: size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
308: size_of_digits_in_chars = size_of_digits_in_littlenums
309: * sizeof( LITTLENUM_TYPE );
310: digits_binary_low = (LITTLENUM_TYPE *)
311: alloca (size_of_digits_in_chars);
312: bzero ((char *)digits_binary_low, size_of_digits_in_chars);
313:
314: /* Digits_binary_low[] is allocated and zeroed. */
315:
316: {
317: /*
318: * Parse the decimal digits as if * digits_low was in the units position.
319: * Emit a binary number into digits_binary_low[].
320: *
321: * Use a large-precision version of:
322: * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
323: */
324:
325: char * p;
326: char c;
327: int count; /* Number of useful digits left to scan. */
328:
329: for (p = first_digit, count = number_of_digits_to_use;
330: count;
331: p ++, -- count)
332: {
333: c = * p;
334: if (isdigit(c))
335: {
336: /*
337: * Multiply by 10. Assume can never overflow.
338: * Add this digit to digits_binary_low[].
339: */
340:
341: long int carry;
342: LITTLENUM_TYPE * littlenum_pointer;
343: LITTLENUM_TYPE * littlenum_limit;
344:
345: littlenum_limit
346: = digits_binary_low
347: + more_than_enough_littlenums_for_digits
348: - 1;
349: carry = c - '0'; /* char -> binary */
350: for (littlenum_pointer = digits_binary_low;
351: littlenum_pointer <= littlenum_limit;
352: littlenum_pointer ++)
353: {
354: long int work;
355:
1.1.1.2 root 356: work = carry + 10 * (long)(*littlenum_pointer);
1.1 root 357: * littlenum_pointer = work & LITTLENUM_MASK;
358: carry = work >> LITTLENUM_NUMBER_OF_BITS;
359: }
360: if (carry != 0)
361: {
362: /*
363: * We have a GROSS internal error.
364: * This should never happen.
365: */
366: abort(); /* RMS prefers abort() to any message. */
367: }
368: }
369: else
370: {
371: ++ count; /* '.' doesn't alter digits used count. */
372: } /* if valid digit */
373: } /* for each digit */
374: }
375:
376: /*
377: * Digits_binary_low[] properly encodes the value of the digits.
378: * Forget about any high-order littlenums that are 0.
379: */
1.1.1.3 ! root 380: while (digits_binary_low [size_of_digits_in_littlenums - 1] == 0
! 381: && size_of_digits_in_littlenums >= 2)
1.1 root 382: size_of_digits_in_littlenums --;
383:
384: digits_flonum . low = digits_binary_low;
385: digits_flonum . high = digits_binary_low + size_of_digits_in_littlenums - 1;
386: digits_flonum . leader = digits_flonum . high;
387: digits_flonum . exponent = 0;
388: /*
389: * The value of digits_flonum . sign should not be important.
1.1.1.3 ! root 390: * We have already decided the output's sign.
1.1 root 391: * We trust that the sign won't influence the other parts of the number!
392: * So we give it a value for these reasons:
393: * (1) courtesy to humans reading/debugging
394: * these numbers so they don't get excited about strange values
395: * (2) in future there may be more meaning attached to sign,
396: * and what was
397: * harmless noise may become disruptive, ill-conditioned (or worse)
398: * input.
399: */
400: digits_flonum . sign = '+';
401:
402: {
403: /*
404: * Compute the mantssa (& exponent) of the power of 10.
405: * If sucessful, then multiply the power of 10 by the digits
406: * giving return_binary_mantissa and return_binary_exponent.
407: */
408:
409: LITTLENUM_TYPE *power_binary_low;
410: int decimal_exponent_is_negative;
411: /* This refers to the "-56" in "12.34E-56". */
412: /* FALSE: decimal_exponent is positive (or 0) */
413: /* TRUE: decimal_exponent is negative */
414: FLONUM_TYPE temporary_flonum;
415: LITTLENUM_TYPE *temporary_binary_low;
416: int size_of_power_in_littlenums;
417: int size_of_power_in_chars;
418:
419: size_of_power_in_littlenums = precision;
420: /* Precision has a built-in fudge factor so we get a few guard bits. */
421:
422:
423: decimal_exponent_is_negative = decimal_exponent < 0;
424: if (decimal_exponent_is_negative)
425: {
426: decimal_exponent = - decimal_exponent;
427: }
428: /* From now on: the decimal exponent is > 0. Its sign is seperate. */
429:
430: size_of_power_in_chars
431: = size_of_power_in_littlenums
1.1.1.3 ! root 432: * sizeof( LITTLENUM_TYPE ) + 2;
1.1 root 433: power_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars );
434: temporary_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars );
435: bzero ((char *)power_binary_low, size_of_power_in_chars);
436: * power_binary_low = 1;
437: power_of_10_flonum . exponent = 0;
438: power_of_10_flonum . low = power_binary_low;
439: power_of_10_flonum . leader = power_binary_low;
440: power_of_10_flonum . high = power_binary_low + size_of_power_in_littlenums - 1;
441: power_of_10_flonum . sign = '+';
442: temporary_flonum . low = temporary_binary_low;
443: temporary_flonum . high = temporary_binary_low + size_of_power_in_littlenums - 1;
444: /*
445: * (power) == 1.
446: * Space for temporary_flonum allocated.
447: */
448:
449: /*
450: * ...
451: *
452: * WHILE more bits
453: * DO find next bit (with place value)
454: * multiply into power mantissa
455: * OD
456: */
457: {
458: int place_number_limit;
459: /* Any 10^(2^n) whose "n" exceeds this */
460: /* value will fall off the end of */
461: /* flonum_XXXX_powers_of_ten[]. */
462: int place_number;
463: FLONUM_TYPE * multiplicand; /* -> 10^(2^n) */
464:
465: place_number_limit = table_size_of_flonum_powers_of_ten;
466: multiplicand
467: = ( decimal_exponent_is_negative
468: ? flonum_negative_powers_of_ten
469: : flonum_positive_powers_of_ten);
470: for (place_number = 1; /* Place value of this bit of exponent. */
471: decimal_exponent; /* Quit when no more 1 bits in exponent. */
472: decimal_exponent >>= 1
473: , place_number ++)
474: {
475: if (decimal_exponent & 1)
476: {
477: if (place_number > place_number_limit)
478: {
479: /*
480: * The decimal exponent has a magnitude so great that
481: * our tables can't help us fragment it. Although this
482: * routine is in error because it can't imagine a
483: * number that big, signal an error as if it is the
484: * user's fault for presenting such a big number.
485: */
486: return_value = ERROR_EXPONENT_OVERFLOW;
487: /*
488: * quit out of loop gracefully
489: */
490: decimal_exponent = 0;
491: }
492: else
493: {
494: #ifdef TRACE
495: printf("before multiply, place_number = %d., power_of_10_flonum:\n", place_number);
496: flonum_print( & power_of_10_flonum );
497: (void)putchar('\n');
498: #endif
499: flonum_multip (multiplicand + place_number, & power_of_10_flonum, & temporary_flonum);
500: flonum_copy (& temporary_flonum, & power_of_10_flonum);
501: } /* If this bit of decimal_exponent was computable.*/
502: } /* If this bit of decimal_exponent was set. */
503: } /* For each bit of binary representation of exponent */
504: #ifdef TRACE
505: printf( " after computing power_of_10_flonum: " );
506: flonum_print( & power_of_10_flonum );
507: (void)putchar('\n');
508: #endif
509: }
510:
511: }
512:
513: /*
514: * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
515: * It may be the number 1, in which case we don't NEED to multiply.
516: *
517: * Multiply (decimal digits) by power_of_10_flonum.
518: */
519:
520: flonum_multip (& power_of_10_flonum, & digits_flonum, address_of_generic_floating_point_number);
521: /* Assert sign of the number we made is '+'. */
522: address_of_generic_floating_point_number -> sign = digits_sign_char;
523:
524: } /* If we had any significant digits. */
525: return (return_value);
526: } /* atof_generic () */
527:
528: /* end: atof_generic.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.