summaryrefslogtreecommitdiffstats
path: root/private/crt32/convert/gcvt.c
blob: a720725fc7f367b78a245922bd926297f20e3203 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/***
*gcvt.c - convert floating point number to character string
*
*	Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
*
*Purpose:
*	Converts floating point number into character string representation.
*
*Revision History:
*	09-09-93  RKW	written
*	11-09-87  BCM	different interface under ifdef MTHREAD
*	12-11-87  JCR	Added "_LOAD_DS" to declaration
*	05-24-88  PHG	Merged DLL and normal versions
*	10-20-88  JCR	Changed 'DOUBLE' to 'double' for 386
*	06-27-89  PHG	Changed "ndec" to "ndec-1" to correct significant
*			digits in exponential format (C6 bug #2124)
*	03-05-90  GJF	Fixed calling type, added #include <cruntime.h>,
*			removed #include <register.h>, removed redundant
*			prototypes, removed some leftover 16-bit support and
*			fixed the copyright. Also, cleaned up the formatting
*			a bit.
*	07-20-90  SBM	Compiles cleanly with -W3 (added/removed appropriate
*			#includes)
*	08-01-90  SBM	Renamed <struct.h> to <fltintrn.h>
*	09-27-90  GJF	New-style function declarators.
*	01-21-91  GJF	ANSI naming.
*	08-13-92  SKS	An old bug that was fixed in C 6.0 but that did not
*			make it into C 7.0, an off by 1 error when switching
*			from fixed point to scientific notation
*
*******************************************************************************/

#include <cruntime.h>
#include <fltintrn.h>
#include <internal.h>

/***
*double _gcvt(value, ndec, buffer) - convert floating point value to char
*	string
*
*Purpose:
*	_gcvt converts the value to a null terminated ASCII string
*	buf.  It attempts to produce ndigit significant digits
*	in Fortran F format if possible, ortherwise E format,
*	ready for printing.  Trailing zeros may be suppressed.
*	No error checking or overflow protection is provided.
*	NOTE - to avoid the possibility of generating floating
*	point instructions in this code we fool the compiler
*	about the type of the 'value' parameter using a struct.
*	This is OK since all we do is pass it off as a
*	parameter.
*
*Entry:
*	value - double - number to be converted
*	ndec - int - number of significant digits
*	buf - char * - buffer to place result
*
*Exit:
*	result is written into buffer; it will be overwritten if it has
*	not been made big enough.
*
*Exceptions:
*
*******************************************************************************/

char * _CALLTYPE1 _gcvt (
	double value,
	int ndec,
	char *buf
	)
{

#ifdef	MTHREAD
	struct _strflt strfltstruct;	/* temporary buffers */
	char   resultstring[21];
#endif

	STRFLT string;
	int    magnitude;
	char   *rc;

	REG1 char *str;
	REG2 char *stop;

	/* get the magnitude of the number */

#ifdef	MTHREAD
	string = _fltout2( value, &strfltstruct, resultstring );
#else
	string = _fltout( value );
#endif

	magnitude = string->decpt - 1;

	/* output the result according to the Fortran G format as outlined in
	   Fortran language specification */

	if ( magnitude < -1  ||  magnitude > ndec-1 )
		/* then  Ew.d  d = ndec */
		rc = str = _cftoe( &value, buf, ndec-1, 0);
	else
		/* Fw.d  where d = ndec-string->decpt */
		rc = str = _cftof( &value, buf, ndec-string->decpt );

	while (*str && *str != '.')
		str++;

	if (*str++) {
		while (*str && *str != 'e')
			str++;

		stop = str--;

		while (*str == '0')
			str--;

		while (*++str = *stop++)
			;
	}

	return(rc);
}