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 2005 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 #pragma weak fconvert = _fconvert 30 #pragma weak sfconvert = _sfconvert 31 #pragma weak qfconvert = _qfconvert 32 33 #include "synonyms.h" 34 #include "base_conversion.h" 35 #include <sys/types.h> 36 #include "libc.h" 37 38 char * 39 fconvert(double arg, int ndigits, int *decpt, int *sign, char *buf) 40 { 41 decimal_mode dm; 42 decimal_record dr; 43 fp_exception_field_type ef; 44 int i; 45 46 #if defined(__sparc) 47 dm.rd = _QgetRD(); 48 #elif defined(__i386) || defined(__amd64) 49 dm.rd = __xgetRD(); 50 #else 51 #error Unknown architecture 52 #endif 53 dm.df = fixed_form; /* F format. */ 54 if (ndigits <= -DECIMAL_STRING_LENGTH) 55 ndigits = -DECIMAL_STRING_LENGTH + 1; 56 else if (ndigits >= DECIMAL_STRING_LENGTH) 57 ndigits = DECIMAL_STRING_LENGTH - 1; 58 dm.ndigits = ndigits; /* Number of digits after point. */ 59 double_to_decimal(&arg, &dm, &dr, &ef); 60 *sign = dr.sign; 61 switch (dr.fpclass) { 62 case fp_normal: 63 case fp_subnormal: 64 *decpt = dr.exponent + dr.ndigits; 65 for (i = 0; i < dr.ndigits; i++) 66 buf[i] = dr.ds[i]; 67 /* 68 * Pad with zeroes if we didn't get all the digits 69 * we asked for. 70 */ 71 if (ndigits > 0 && dr.exponent > -ndigits) { 72 while (i < dr.ndigits + dr.exponent + ndigits) 73 buf[i++] = '0'; 74 } 75 buf[i] = 0; 76 break; 77 case fp_zero: 78 *decpt = 0; 79 buf[0] = '0'; 80 for (i = 1; i < ndigits; i++) 81 buf[i] = '0'; 82 buf[i] = 0; 83 break; 84 default: 85 *decpt = 0; 86 __infnanstring(dr.fpclass, ndigits, buf); 87 break; 88 } 89 return (buf); 90 } 91 92 char * 93 sfconvert(single *arg, int ndigits, int *decpt, int *sign, char *buf) 94 { 95 decimal_mode dm; 96 decimal_record dr; 97 fp_exception_field_type ef; 98 int i; 99 100 #if defined(__sparc) 101 dm.rd = _QgetRD(); 102 #elif defined(__i386) || defined(__amd64) 103 dm.rd = __xgetRD(); 104 #else 105 #error Unknown architecture 106 #endif 107 dm.df = fixed_form; /* F format. */ 108 if (ndigits <= -DECIMAL_STRING_LENGTH) 109 ndigits = -DECIMAL_STRING_LENGTH + 1; 110 else if (ndigits >= DECIMAL_STRING_LENGTH) 111 ndigits = DECIMAL_STRING_LENGTH - 1; 112 dm.ndigits = ndigits; /* Number of digits after point. */ 113 single_to_decimal(arg, &dm, &dr, &ef); 114 *sign = dr.sign; 115 switch (dr.fpclass) { 116 case fp_normal: 117 case fp_subnormal: 118 *decpt = dr.exponent + dr.ndigits; 119 for (i = 0; i < dr.ndigits; i++) 120 buf[i] = dr.ds[i]; 121 /* 122 * Pad with zeroes if we didn't get all the digits 123 * we asked for. 124 */ 125 if (ndigits > 0 && dr.exponent > -ndigits) { 126 while (i < dr.ndigits + dr.exponent + ndigits) 127 buf[i++] = '0'; 128 } 129 buf[i] = 0; 130 break; 131 case fp_zero: 132 *decpt = 0; 133 buf[0] = '0'; 134 for (i = 1; i < ndigits; i++) 135 buf[i] = '0'; 136 buf[i] = 0; 137 break; 138 default: 139 *decpt = 0; 140 __infnanstring(dr.fpclass, ndigits, buf); 141 break; 142 } 143 return (buf); 144 } 145 146 char * 147 qfconvert(quadruple *arg, int ndigits, int *decpt, int *sign, char *buf) 148 { 149 decimal_mode dm; 150 decimal_record dr; 151 fp_exception_field_type ef; 152 int i; 153 154 #if defined(__sparc) 155 dm.rd = _QgetRD(); 156 #elif defined(__i386) || defined(__amd64) 157 dm.rd = __xgetRD(); 158 #else 159 #error Unknown architecture 160 #endif 161 dm.df = fixed_form; /* F format. */ 162 if (ndigits <= -DECIMAL_STRING_LENGTH) 163 ndigits = -DECIMAL_STRING_LENGTH + 1; 164 else if (ndigits >= DECIMAL_STRING_LENGTH) 165 ndigits = DECIMAL_STRING_LENGTH - 1; 166 dm.ndigits = ndigits; /* Number of digits after point. */ 167 #if defined(__sparc) 168 quadruple_to_decimal(arg, &dm, &dr, &ef); 169 #elif defined(__i386) || defined(__amd64) 170 extended_to_decimal((extended *)arg, &dm, &dr, &ef); 171 #else 172 #error Unknown architecture 173 #endif 174 *sign = dr.sign; 175 if (ef & (1 << fp_overflow)) { 176 /* 177 * *_to_decimal raises overflow whenever dr.ds isn't large 178 * enough to hold all the digits requested. For float and 179 * double, this can only happen when the requested format 180 * would require trailing zeroes, in which case fconvert 181 * and sfconvert just add them. For long double, the arg- 182 * ument might be large enough that even the nonzero digits 183 * would overflow dr.ds, so we punt instead. (We could 184 * distinguish these two cases, but it doesn't seem worth 185 * changing things now, particularly since no real appli- 186 * cation prints floating point numbers to 500 digits.) 187 */ 188 *decpt = 0; 189 buf[0] = 0; 190 return (buf); 191 } 192 switch (dr.fpclass) { 193 case fp_normal: 194 case fp_subnormal: 195 *decpt = dr.exponent + dr.ndigits; 196 for (i = 0; i < dr.ndigits; i++) 197 buf[i] = dr.ds[i]; 198 buf[i] = 0; 199 break; 200 case fp_zero: 201 *decpt = 0; 202 buf[0] = '0'; 203 for (i = 1; i < ndigits; i++) 204 buf[i] = '0'; 205 buf[i] = 0; 206 break; 207 default: 208 *decpt = 0; 209 __infnanstring(dr.fpclass, ndigits, buf); 210 break; 211 } 212 return (buf); 213 } 214