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