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