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