xref: /illumos-gate/usr/src/lib/libc/port/gen/strtod.c (revision 7257d1b4)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include "lint.h"
33 #include <errno.h>
34 #include <stdio.h>
35 #include <values.h>
36 #include <floatingpoint.h>
37 #include <stdlib.h>
38 #include <sys/types.h>
39 #include "libc.h"
40 #include "xpg6.h"
41 
42 double
43 strtod(const char *cp, char **ptr)
44 {
45 	double		x;
46 	decimal_mode	mr;
47 	decimal_record  dr;
48 	fp_exception_field_type fs;
49 	enum decimal_string_form form;
50 	char		*pechar;
51 	int		lc;
52 
53 	lc = (__xpg6 & _C99SUSv3_recognize_hexfp)? -1 : 0;
54 	string_to_decimal((char **)&cp, MAXINT, lc, &dr, &form, &pechar);
55 	if (ptr != NULL)
56 		*ptr = (char *)cp;
57 	if (form == invalid_form)
58 		return (0.0);	/* Shameful kluge for SVID's sake. */
59 #if defined(__sparc)
60 	mr.rd = _QgetRD();
61 #elif defined(__i386) || defined(__amd64)
62 	mr.rd = __xgetRD();
63 #else
64 #error Unknown architecture
65 #endif
66 	if ((int)form < 0)
67 		__hex_to_double(&dr, mr.rd, &x, &fs);
68 	else
69 		decimal_to_double(&x, &mr, &dr, &fs);
70 	if (fs & ((1 << fp_overflow) | (1 << fp_underflow)))
71 		errno = ERANGE;
72 	return (x);
73 }
74 
75 float
76 strtof(const char *cp, char **ptr)
77 {
78 	float		x;
79 	decimal_mode	mr;
80 	decimal_record	dr;
81 	fp_exception_field_type fs;
82 	enum decimal_string_form form;
83 	char		*pechar;
84 
85 	string_to_decimal((char **)&cp, MAXINT, -1, &dr, &form, &pechar);
86 	if (ptr != NULL)
87 		*ptr = (char *)cp;
88 	if (form == invalid_form)
89 		return (0.0f);
90 #if defined(__sparc)
91 	mr.rd = _QgetRD();
92 #elif defined(__i386) || defined(__amd64)
93 	mr.rd = __xgetRD();
94 #else
95 #error Unknown architecture
96 #endif
97 	if ((int)form < 0)
98 		__hex_to_single(&dr, mr.rd, &x, &fs);
99 	else
100 		decimal_to_single(&x, &mr, &dr, &fs);
101 	if (fs & ((1 << fp_overflow) | (1 << fp_underflow)))
102 		errno = ERANGE;
103 	return (x);
104 }
105 
106 long double
107 strtold(const char *cp, char **ptr)
108 {
109 	long double	x;
110 	decimal_mode	mr;
111 	decimal_record	dr;
112 	fp_exception_field_type fs;
113 	enum decimal_string_form form;
114 	char		*pechar;
115 
116 	string_to_decimal((char **)&cp, MAXINT, -1, &dr, &form, &pechar);
117 	if (ptr != NULL)
118 		*ptr = (char *)cp;
119 	if (form == invalid_form)
120 		return (0.0L);
121 #if defined(__sparc)
122 	mr.rd = _QgetRD();
123 	if ((int)form < 0)
124 		__hex_to_quadruple(&dr, mr.rd, &x, &fs);
125 	else
126 		decimal_to_quadruple(&x, &mr, &dr, &fs);
127 #elif defined(__i386) || defined(__amd64)
128 	mr.rd = __xgetRD();
129 	if ((int)form < 0)
130 		__hex_to_extended(&dr, mr.rd, (extended *)&x, &fs);
131 	else
132 		decimal_to_extended((extended *)&x, &mr, &dr, &fs);
133 #else
134 #error Unknown architecture
135 #endif
136 	if (fs & ((1 << fp_overflow) | (1 << fp_underflow)))
137 		errno = ERANGE;
138 	return (x);
139 }
140