source: trunk/src/binutils/gas/atof-generic.c@ 10

Last change on this file since 10 was 10, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 18.0 KB
Line 
1/* atof_generic.c - turn a string of digits into a Flonum
2 Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000
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 <ctype.h>
23#include <string.h>
24
25#include "as.h"
26
27#ifndef FALSE
28#define FALSE (0)
29#endif
30#ifndef TRUE
31#define TRUE (1)
32#endif
33
34#ifdef TRACE
35static void flonum_print PARAMS ((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
77int
78atof_generic (address_of_string_pointer,
79 string_of_decimal_marks,
80 string_of_decimal_exponent_marks,
81 address_of_generic_floating_point_number)
82 /* return pointer to just AFTER number we read. */
83 char **address_of_string_pointer;
84 /* At most one per number. */
85 const char *string_of_decimal_marks;
86 const char *string_of_decimal_exponent_marks;
87 FLONUM_TYPE *address_of_generic_floating_point_number;
88{
89 int return_value; /* 0 means OK. */
90 char *first_digit;
91 unsigned int number_of_digits_before_decimal;
92 unsigned int number_of_digits_after_decimal;
93 long decimal_exponent;
94 unsigned int number_of_digits_available;
95 char digits_sign_char;
96
97 /*
98 * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
99 * It would be simpler to modify the string, but we don't; just to be nice
100 * to caller.
101 * We need to know how many digits we have, so we can allocate space for
102 * the digits' value.
103 */
104
105 char *p;
106 char c;
107 int seen_significant_digit;
108
109#ifdef ASSUME_DECIMAL_MARK_IS_DOT
110 assert (string_of_decimal_marks[0] == '.'
111 && string_of_decimal_marks[1] == 0);
112#define IS_DECIMAL_MARK(c) ((c) == '.')
113#else
114#define IS_DECIMAL_MARK(c) (0 != strchr (string_of_decimal_marks, (c)))
115#endif
116
117 first_digit = *address_of_string_pointer;
118 c = *first_digit;
119
120 if (c == '-' || c == '+')
121 {
122 digits_sign_char = c;
123 first_digit++;
124 }
125 else
126 digits_sign_char = '+';
127
128 switch (first_digit[0])
129 {
130 case 'n':
131 case 'N':
132 if (!strncasecmp ("nan", first_digit, 3))
133 {
134 address_of_generic_floating_point_number->sign = 0;
135 address_of_generic_floating_point_number->exponent = 0;
136 address_of_generic_floating_point_number->leader =
137 address_of_generic_floating_point_number->low;
138 *address_of_string_pointer = first_digit + 3;
139 return 0;
140 }
141 break;
142
143 case 'i':
144 case 'I':
145 if (!strncasecmp ("inf", first_digit, 3))
146 {
147 address_of_generic_floating_point_number->sign =
148 digits_sign_char == '+' ? 'P' : 'N';
149 address_of_generic_floating_point_number->exponent = 0;
150 address_of_generic_floating_point_number->leader =
151 address_of_generic_floating_point_number->low;
152
153 first_digit += 3;
154 if (!strncasecmp ("inity", first_digit, 5))
155 first_digit += 5;
156
157 *address_of_string_pointer = first_digit;
158
159 return 0;
160 }
161 break;
162 }
163
164 number_of_digits_before_decimal = 0;
165 number_of_digits_after_decimal = 0;
166 decimal_exponent = 0;
167 seen_significant_digit = 0;
168 for (p = first_digit;
169 (((c = *p) != '\0')
170 && (!c || !IS_DECIMAL_MARK (c))
171 && (!c || !strchr (string_of_decimal_exponent_marks, c)));
172 p++)
173 {
174 if (isdigit ((unsigned char) c))
175 {
176 if (seen_significant_digit || c > '0')
177 {
178 ++number_of_digits_before_decimal;
179 seen_significant_digit = 1;
180 }