master
  1/****************************************************************
  2
  3The author of this software is David M. Gay.
  4
  5Copyright (C) 1998 by Lucent Technologies
  6All Rights Reserved
  7
  8Permission to use, copy, modify, and distribute this software and
  9its documentation for any purpose and without fee is hereby
 10granted, provided that the above copyright notice appear in all
 11copies and that both that the copyright notice and this
 12permission notice and warranty disclaimer appear in supporting
 13documentation, and that the name of Lucent or any of its entities
 14not be used in advertising or publicity pertaining to
 15distribution of the software without specific, written prior
 16permission.
 17
 18LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 19INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
 20IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
 21SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 23IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 24ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 25THIS SOFTWARE.
 26
 27****************************************************************/
 28
 29/* Please send bug reports to David M. Gay (dmg at acm dot org,
 30 * with " at " changed at "@" and " dot " changed to ".").	*/
 31
 32#include "gdtoaimp.h"
 33
 34#ifdef USE_LOCALE
 35#include "locale.h"
 36#endif
 37
 38#ifndef ldus_QNAN0
 39#define ldus_QNAN0 0x7fff
 40#endif
 41#ifndef ldus_QNAN1
 42#define ldus_QNAN1 0xc000
 43#endif
 44#ifndef ldus_QNAN2
 45#define ldus_QNAN2 0
 46#endif
 47#ifndef ldus_QNAN3
 48#define ldus_QNAN3 0
 49#endif
 50#ifndef ldus_QNAN4
 51#define ldus_QNAN4 0
 52#endif
 53
 54 const char *InfName[6] = { "Infinity", "infinity", "INFINITY", "Inf", "inf", "INF" };
 55 const char *NanName[3] = { "NaN", "nan", "NAN" };
 56 ULong NanDflt_Q_D2A[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff };
 57 ULong NanDflt_d_D2A[2] = { d_QNAN1, d_QNAN0 };
 58 ULong NanDflt_f_D2A[1] = { f_QNAN };
 59 ULong NanDflt_xL_D2A[3] = { 1, 0x80000000, 0x7fff0000 };
 60 UShort NanDflt_ldus_D2A[5] = { ldus_QNAN4, ldus_QNAN3, ldus_QNAN2, ldus_QNAN1, ldus_QNAN0 };
 61
 62char *__g__fmt (char *b, char *s, char *se, int decpt, ULong sign, size_t blen)
 63{
 64	int i, j, k;
 65	char *be, *s0;
 66	size_t len;
 67#ifdef USE_LOCALE
 68#ifdef NO_LOCALE_CACHE
 69	char *decimalpoint = localeconv()->decimal_point;
 70	size_t dlen = strlen(decimalpoint);
 71#else
 72	char *decimalpoint;
 73	static char *decimalpoint_cache;
 74	static size_t dlen;
 75	if (!(s0 = decimalpoint_cache)) {
 76		s0 = localeconv()->decimal_point;
 77		dlen = strlen(s0);
 78		if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
 79			strcpy(decimalpoint_cache, s0);
 80			s0 = decimalpoint_cache;
 81		}
 82	}
 83	decimalpoint = s0;
 84#endif
 85#else
 86#define dlen 0
 87#endif
 88	s0 = s;
 89	len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */
 90	if (blen < len)
 91		goto ret0;
 92	be = b + blen - 1;
 93	if (sign)
 94		*b++ = '-';
 95	if (decpt <= -4 || decpt > se - s + 5) {
 96		*b++ = *s++;
 97		if (*s) {
 98#ifdef USE_LOCALE
 99			while((*b = *decimalpoint++))
100				++b;
101#else
102			*b++ = '.';
103#endif
104			while((*b = *s++) !=0)
105				b++;
106		}
107		*b++ = 'e';
108		/* sprintf(b, "%+.2d", decpt - 1); */
109		if (--decpt < 0) {
110			*b++ = '-';
111			decpt = -decpt;
112		}
113		else
114			*b++ = '+';
115		for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){}
116		for(;;) {
117			i = decpt / k;
118			if (b >= be)
119				goto ret0;
120			*b++ = i + '0';
121			if (--j <= 0)
122				break;
123			decpt -= i*k;
124			decpt *= 10;
125		}
126		*b = 0;
127	}
128	else if (decpt <= 0) {
129#ifdef USE_LOCALE
130		while((*b = *decimalpoint++))
131			++b;
132#else
133		*b++ = '.';
134#endif
135		if (be < b - decpt + (se - s))
136			goto ret0;
137		for(; decpt < 0; decpt++)
138			*b++ = '0';
139		while((*b = *s++) != 0)
140			b++;
141	}
142	else {
143		while((*b = *s++) != 0) {
144			b++;
145			if (--decpt == 0 && *s) {
146#ifdef USE_LOCALE
147				while((*b = *decimalpoint++))
148					++b;
149#else
150				*b++ = '.';
151#endif
152			}
153		}
154		if (b + decpt > be) {
155 ret0:
156			b = 0;
157			goto ret;
158		}
159		for(; decpt > 0; decpt--)
160			*b++ = '0';
161		*b = 0;
162	}
163 ret:
164	__freedtoa(s0);
165	return b;
166}
167
168 char *
169__add_nanbits_D2A(char *b, size_t blen, ULong *bits, int nb)
170{
171	ULong t;
172	char *rv;
173	int i, j;
174	size_t L;
175	static char Hexdig[16] = "0123456789abcdef";
176
177	while(!bits[--nb])
178		if (!nb)
179			return b;
180	L = 8*nb + 3;
181	t = bits[nb];
182	do ++L; while((t >>= 4));
183	if (L > blen)
184		return b;
185	b += L;
186	*--b = 0;
187	rv = b;
188	*--b = /*(*/ ')';
189	for(i = 0; i < nb; ++i) {
190		t = bits[i];
191		for(j = 0; j < 8; ++j, t >>= 4)
192			*--b = Hexdig[t & 0xf];
193		}
194	t = bits[nb];
195	do *--b = Hexdig[t & 0xf]; while(t >>= 4);
196	*--b = '('; /*)*/
197	return rv;
198	}