summaryrefslogtreecommitdiffstats
path: root/private/crt32/convert/fcvt.c
blob: 92bb49b3f592e10b35ec667c7346008f4d181f21 (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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/***
*fcvt.c - convert floating point value to string
*
*	Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*	Converts a floating point value to a string.
*
*Revision History:
*	09-09-83  RKW	written
*	09-14-84  DFW	fixed problems with buffer overflow and
*			streamlined the code
*	11-09-87  BCM	different interface under ifdef MTHREAD
*	11-19-87  WAJ	fcvt now uses emulator data area for buffer
*	12-11-87  JCR	Added "_LOAD_DS" to declaration
*	05-24-88  PHG	Merged DLL and normal versions
*	10-04-88  JCR	386: Removed 'far' keyword
*	10-20-88  JCR	Changed 'DOUBLE' to 'double' for 386
*	03-02-90  GJF	Added #include <cruntime.h>. Removed some (now) useless
*			preprocessor directives. Also, fixed copyright.
*	03-06-90  GJF	Fixed calling type, removed some leftover 16-bit
*			support.
*	03-23-90  GJF	Made _fpcvt() _CALLTYPE4 and removed prototype for
*			_fptostr() (now in struct.h).
*	08-01-90  SBM	Renamed <struct.h> to <fltintrn.h>
*	09-27-90  GJF	New-style function declarators.
*	01-21-91  GJF	ANSI naming.
*	10-03-91  JCR	Fixed mthread buffer allocation
*	02-16-93  GJF	Changed for new _getptd().
*
*******************************************************************************/

#include <cruntime.h>
#include <fltintrn.h>
#include <cvt.h>
#include <os2dll.h>
#include <stdlib.h>

/*
 * The static character array buf[CVTBUFSIZE] is used by the _fpcvt routine
 * (the workhorse for _ecvt and _fcvt) for storage of its output.  The routine
 * gcvt expects the user to have set up their own storage.  CVTBUFSIZE is set
 * large enough to accomodate the largest double precision number plus 40
 * decimal places (even though you only have 16 digits of accuracy in a
 * double precision IEEE number, the user may ask for more to effect 0
 * padding; but there has to be a limit somewhere).
 */

/*
 * define a maximum size for the conversion buffer.  It should be at least
 * as long as the number of digits in the largest double precision value
 * (?.?e308 in IEEE arithmetic).  We will use the same size buffer as is
 * used in the printf support routine (_output)
 */

#ifdef	MTHREAD
char * _CRTAPI3 _fpcvt(STRFLT, int, int *, int *);
#else
static char * _CRTAPI3 _fpcvt(STRFLT, int, int *, int *);
static char buf[CVTBUFSIZE];
#endif

/***
*char *_fcvt(value, ndec, decpr, sign) - convert floating point to char string
*
*Purpose:
*	_fcvt like _ecvt converts the value to a null terminated
*	string of ASCII digits, and returns a pointer to the
*	result.  The routine prepares data for Fortran F-format
*	output with the number of digits following the decimal
*	point specified by ndec.  The position of the decimal
*	point relative to the beginning of the string is returned
*	indirectly through decpt.  The correct digit for Fortran
*	F-format is rounded.
*	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:
*	double value - number to be converted
*	int ndec - number of digits after decimal point
*
*Exit:
*	returns pointer to the character string representation of value.
*	also, the output is written into the static char array buf.
*	int *decpt - pointer to int with pos. of dec. point
*	int *sign - pointer to int with sign (0 = pos, non-0 = neg)
*
*Exceptions:
*
*******************************************************************************/

char * _CRTAPI1 _fcvt (
	double value,
	int ndec,
	int *decpt,
	int *sign
	)
{
	REG1 STRFLT pflt;

#ifdef	MTHREAD
	struct _strflt strfltstruct;
	char resultstring[21];

	/* ok to take address of stack struct here; fltout2 knows to use ss */
	pflt = _fltout2( value, &strfltstruct, resultstring );


#else
	pflt = _fltout( value );
#endif

	return( _fpcvt( pflt, pflt->decpt + ndec, decpt, sign ) );
}


/***
*char *_ecvt( value, ndigit, decpt, sign ) - convert floating point to string
*
*Purpose:
*	_ecvt converts value to a null terminated string of
*	ASCII digits, and returns a pointer to the result.
*	The position of the decimal point relative to the
*	begining of the string is stored indirectly through
*	decpt, where negative means to the left of the returned
*	digits.  If the sign of the result is negative, the
*	word pointed to by sign is non zero, otherwise it is
*	zero.  The low order digit is rounded.
*
*Entry:
*	double value - number to be converted
*	int ndigit - number of digits after decimal point
*
*Exit:
*	returns pointer to the character representation of value.
*	also the output is written into the statuc char array buf.
*	int *decpt - pointer to int with position of decimal point
*	int *sign - pointer to int with sign in it (0 = pos, non-0 = neg)
*
*Exceptions:
*
*******************************************************************************/

char * _CRTAPI1 _ecvt (
	double value,
	int ndigit,
	int *decpt,
	int *sign
	)
{

#ifdef	MTHREAD
	REG1 STRFLT pflt;

	struct _strflt strfltstruct;	    /* temporary buffers */
	char resultstring[21];

	/* ok to take address of stack struct here; fltout2 knows to use ss */
	pflt = _fltout2( value, &strfltstruct, resultstring );

	return( _fpcvt( pflt, ndigit, decpt, sign ) );

#else
	return( _fpcvt( _fltout(value), ndigit, decpt, sign ) );
#endif
}


/***
*char *_fpcvt() - gets final string and sets decpt and sign	[STATIC]
*
*Purpose:
*	This is a small common routine used by [ef]cvt.  It calls fptostr
*	to get the final string and sets the decpt and sign indicators.
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/

#ifdef	MTHREAD
char * _CRTAPI3 _fpcvt (
#else
static char * _CRTAPI3 _fpcvt (
#endif
	REG2 STRFLT pflt,
	REG3 int digits,
	int *decpt,
	int *sign
	)
{

#ifdef	MTHREAD

	/* use a per-thread buffer */

	char *buf;

#ifdef _CRUISER_

	struct _tiddata * tdata;

	tdata = _gettidtab();	/* get tid's data address */
	if (tdata->_cvtbuf == NULL)
		if ( (tdata->_cvtbuf = malloc(CVTBUFSIZE)) == NULL)
			return(NULL);
	buf = tdata->_cvtbuf;

#else	/* ndef _CRUISER_ */

#ifdef	_WIN32_

	_ptiddata ptd;

	ptd = _getptd();
	if ( ptd->_cvtbuf == NULL )
		if ( (ptd->_cvtbuf = malloc(CVTBUFSIZE)) == NULL )
			return(NULL);
	buf = ptd->_cvtbuf;

#else	/* ndef _WIN32_ */

#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!

#endif	/* _WIN32_ */

#endif	/* _CRUISER_ */

#endif	/* MTHREAD */


	/* make sure we don't overflow the buffer size.  If the user asks for
	 * more digits than the buffer can handle, truncate it to the maximum
	 * size allowed in the buffer.	The maximum size is CVTBUFSIZE - 2
	 * since we useone character for overflow and one for the terminating
	 * null character.
	 */

	_fptostr(buf, (digits > CVTBUFSIZE - 2) ? CVTBUFSIZE - 2 : digits, pflt);

	/* set the sign flag and decimal point position */

	*sign = (pflt->sign == '-') ? 1 : 0;
	*decpt = pflt->decpt;
	return(buf);
}