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