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 gconvert = _gconvert 30 #pragma weak sgconvert = _sgconvert 31 #pragma weak qgconvert = _qgconvert 32 33 #include "synonyms.h" 34 #include "base_conversion.h" 35 #include <sys/types.h> 36 #include "libc.h" 37 #include <locale.h> 38 39 static void 40 __k_gconvert(int ndigits, decimal_record *pd, int trailing, char *buf) 41 { 42 char *p; 43 int i; 44 char decpt = *(localeconv()->decimal_point); 45 46 p = buf; 47 if (pd->sign) 48 *(p++) = '-'; 49 switch (pd->fpclass) { 50 case fp_zero: 51 *(p++) = '0'; 52 if (trailing != 0) { 53 *(p++) = decpt; 54 for (i = 0; i < ndigits - 1; i++) 55 *(p++) = '0'; 56 } 57 *p++ = 0; 58 break; 59 case fp_subnormal: 60 case fp_normal: 61 if ((pd->exponent > 0) || (pd->exponent < -(ndigits + 3))) { 62 /* E format. */ 63 char estring[4]; 64 int n; 65 66 *(p++) = pd->ds[0]; 67 *(p++) = decpt; 68 for (i = 1; pd->ds[i] != 0; ) 69 *(p++) = pd->ds[i++]; 70 if (trailing == 0) { 71 /* Remove trailing zeros and . */ 72 p--; 73 while (*p == '0') 74 p--; 75 if (*p != decpt) 76 p++; 77 } 78 *(p++) = 'e'; 79 n = pd->exponent + i - 1; 80 if (n >= 0) 81 *(p++) = '+'; 82 else { 83 *(p++) = '-'; 84 n = -n; 85 } 86 __four_digits_quick((unsigned short) n, estring); 87 88 /* Find end of zeros. */ 89 for (i = 0; estring[i] == '0'; i++) 90 ; 91 92 if (i > 2) 93 i = 2; /* Guarantee two zeros. */ 94 for (; i <= 3; ) 95 *(p++) = estring[i++]; /* Copy exp digits. */ 96 } else { /* F format. */ 97 if (pd->exponent >= (1 - ndigits)) { /* x.xxx */ 98 for (i = 0; i < (ndigits + pd->exponent); ) 99 *(p++) = pd->ds[i++]; 100 *(p++) = decpt; 101 if (pd->ds[i] != 0) { 102 /* More follows point. */ 103 for (; i < ndigits; ) 104 *(p++) = pd->ds[i++]; 105 } 106 } else { /* 0.00xxxx */ 107 *(p++) = '0'; 108 *(p++) = decpt; 109 for (i = 0; i < -(pd->exponent + ndigits); i++) 110 *(p++) = '0'; 111 for (i = 0; pd->ds[i] != 0; ) 112 *(p++) = pd->ds[i++]; 113 } 114 if (trailing == 0) { 115 /* Remove trailing zeros and point. */ 116 p--; 117 while (*p == '0') 118 p--; 119 if (*p != decpt) 120 p++; 121 } 122 } 123 *(p++) = 0; 124 break; 125 default: 126 __infnanstring(pd->fpclass, ndigits, p); 127 break; 128 } 129 } 130 131 char * 132 gconvert(double number, int ndigits, int trailing, char *buf) 133 { 134 decimal_mode dm; 135 decimal_record dr; 136 fp_exception_field_type fef; 137 138 #if defined(__sparc) 139 dm.rd = _QgetRD(); 140 #elif defined(__i386) || defined(__amd64) 141 dm.rd = __xgetRD(); 142 #else 143 #error Unknown architecture 144 #endif 145 dm.df = floating_form; 146 if (ndigits < 0) 147 ndigits = 6; 148 else if (ndigits == 0) 149 ndigits = 1; 150 else if (ndigits >= DECIMAL_STRING_LENGTH) 151 ndigits = DECIMAL_STRING_LENGTH - 1; 152 dm.ndigits = ndigits; 153 double_to_decimal(&number, &dm, &dr, &fef); 154 __k_gconvert(ndigits, &dr, trailing, buf); 155 return (buf); 156 } 157 158 char * 159 sgconvert(single *number, int ndigits, int trailing, char *buf) 160 { 161 decimal_mode dm; 162 decimal_record dr; 163 fp_exception_field_type fef; 164 165 #if defined(__sparc) 166 dm.rd = _QgetRD(); 167 #elif defined(__i386) || defined(__amd64) 168 dm.rd = __xgetRD(); 169 #else 170 #error Unknown architecture 171 #endif 172 dm.df = floating_form; 173 if (ndigits < 0) 174 ndigits = 6; 175 else if (ndigits == 0) 176 ndigits = 1; 177 else if (ndigits >= DECIMAL_STRING_LENGTH) 178 ndigits = DECIMAL_STRING_LENGTH - 1; 179 dm.ndigits = ndigits; 180 single_to_decimal(number, &dm, &dr, &fef); 181 __k_gconvert(ndigits, &dr, trailing, buf); 182 return (buf); 183 } 184 185 char * 186 qgconvert(quadruple *number, int ndigits, int trailing, char *buf) 187 { 188 decimal_mode dm; 189 decimal_record dr; 190 fp_exception_field_type fef; 191 192 #if defined(__sparc) 193 dm.rd = _QgetRD(); 194 #elif defined(__i386) || defined(__amd64) 195 dm.rd = __xgetRD(); 196 #else 197 #error Unknown architecture 198 #endif 199 dm.df = floating_form; 200 if (ndigits < 0) 201 ndigits = 6; 202 else if (ndigits == 0) 203 ndigits = 1; 204 else if (ndigits >= DECIMAL_STRING_LENGTH) 205 ndigits = DECIMAL_STRING_LENGTH - 1; 206 dm.ndigits = ndigits; 207 #if defined(__sparc) 208 quadruple_to_decimal(number, &dm, &dr, &fef); 209 #elif defined(__i386) || defined(__amd64) 210 extended_to_decimal((extended *)number, &dm, &dr, &fef); 211 #else 212 #error Unknown architecture 213 #endif 214 __k_gconvert(ndigits, &dr, trailing, buf); 215 return (buf); 216 } 217