Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
7.8 KiB

  1. /***
  2. *fcvt.c - convert floating point value to string
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Converts a floating point value to a string.
  8. *
  9. *Revision History:
  10. * 09-09-83 RKW written
  11. * 09-14-84 DFW fixed problems with buffer overflow and
  12. * streamlined the code
  13. * 11-09-87 BCM different interface under ifdef MTHREAD
  14. * 11-19-87 WAJ fcvt now uses emulator data area for buffer
  15. * 12-11-87 JCR Added "_LOAD_DS" to declaration
  16. * 05-24-88 PHG Merged DLL and normal versions
  17. * 10-04-88 JCR 386: Removed 'far' keyword
  18. * 10-20-88 JCR Changed 'DOUBLE' to 'double' for 386
  19. * 03-02-90 GJF Added #include <cruntime.h>. Removed some (now) useless
  20. * preprocessor directives. Also, fixed copyright.
  21. * 03-06-90 GJF Fixed calling type, removed some leftover 16-bit
  22. * support.
  23. * 03-23-90 GJF Made _fpcvt() _CALLTYPE4 and removed prototype for
  24. * _fptostr() (now in struct.h).
  25. * 08-01-90 SBM Renamed <struct.h> to <fltintrn.h>
  26. * 09-27-90 GJF New-style function declarators.
  27. * 01-21-91 GJF ANSI naming.
  28. * 10-03-91 JCR Fixed mthread buffer allocation
  29. * 02-16-93 GJF Changed for new _getptd().
  30. * 04-06-93 SKS Replace _CRTAPI* with _cdecl
  31. * 08-05-94 JWM Insure that _ecvt returns no more than ndigits.
  32. * 09-06-94 CFW Remove Cruiser support.
  33. * 09-06-94 CFW Replace MTHREAD with _MT.
  34. * 01-10-95 CFW Debug CRT allocs.
  35. * 09-05-00 GB Changed the defination of fltout functions. Use DOUBLE
  36. * instead of double
  37. * 12-11-01 BWT Use _getptd_noexit instead of _getptd. There's no need to
  38. * exit the process when we can just return null.
  39. *
  40. *******************************************************************************/
  41. #include <cruntime.h>
  42. #include <fltintrn.h>
  43. #include <cvt.h>
  44. #include <mtdll.h>
  45. #include <stdlib.h>
  46. #include <dbgint.h>
  47. /*
  48. * The static character array buf[CVTBUFSIZE] is used by the _fpcvt routine
  49. * (the workhorse for _ecvt and _fcvt) for storage of its output. The routine
  50. * gcvt expects the user to have set up their own storage. CVTBUFSIZE is set
  51. * large enough to accomodate the largest double precision number plus 40
  52. * decimal places (even though you only have 16 digits of accuracy in a
  53. * double precision IEEE number, the user may ask for more to effect 0
  54. * padding; but there has to be a limit somewhere).
  55. */
  56. /*
  57. * define a maximum size for the conversion buffer. It should be at least
  58. * as long as the number of digits in the largest double precision value
  59. * (?.?e308 in IEEE arithmetic). We will use the same size buffer as is
  60. * used in the printf support routine (_output)
  61. */
  62. #ifdef _MT
  63. char * __cdecl _fpcvt(STRFLT, int, int *, int *);
  64. #else
  65. static char * __cdecl _fpcvt(STRFLT, int, int *, int *);
  66. static char buf[CVTBUFSIZE];
  67. #endif
  68. /***
  69. *char *_fcvt(value, ndec, decpr, sign) - convert floating point to char string
  70. *
  71. *Purpose:
  72. * _fcvt like _ecvt converts the value to a null terminated
  73. * string of ASCII digits, and returns a pointer to the
  74. * result. The routine prepares data for Fortran F-format
  75. * output with the number of digits following the decimal
  76. * point specified by ndec. The position of the decimal
  77. * point relative to the beginning of the string is returned
  78. * indirectly through decpt. The correct digit for Fortran
  79. * F-format is rounded.
  80. * NOTE - to avoid the possibility of generating floating
  81. * point instructions in this code we fool the compiler
  82. * about the type of the 'value' parameter using a struct.
  83. * This is OK since all we do is pass it off as a
  84. * parameter.
  85. *
  86. *Entry:
  87. * double value - number to be converted
  88. * int ndec - number of digits after decimal point
  89. *
  90. *Exit:
  91. * returns pointer to the character string representation of value.
  92. * also, the output is written into the static char array buf.
  93. * int *decpt - pointer to int with pos. of dec. point
  94. * int *sign - pointer to int with sign (0 = pos, non-0 = neg)
  95. *
  96. *Exceptions:
  97. *
  98. *******************************************************************************/
  99. char * __cdecl _fcvt (
  100. double value,
  101. int ndec,
  102. int *decpt,
  103. int *sign
  104. )
  105. {
  106. REG1 STRFLT pflt;
  107. DOUBLE *pdvalue = (DOUBLE *)&value;
  108. #ifdef _MT
  109. struct _strflt strfltstruct;
  110. char resultstring[21];
  111. /* ok to take address of stack struct here; fltout2 knows to use ss */
  112. pflt = _fltout2( *pdvalue, &strfltstruct, resultstring );
  113. #else
  114. pflt = _fltout( *pdvalue );
  115. #endif
  116. return( _fpcvt( pflt, pflt->decpt + ndec, decpt, sign ) );
  117. }
  118. /***
  119. *char *_ecvt( value, ndigit, decpt, sign ) - convert floating point to string
  120. *
  121. *Purpose:
  122. * _ecvt converts value to a null terminated string of
  123. * ASCII digits, and returns a pointer to the result.
  124. * The position of the decimal point relative to the
  125. * begining of the string is stored indirectly through
  126. * decpt, where negative means to the left of the returned
  127. * digits. If the sign of the result is negative, the
  128. * word pointed to by sign is non zero, otherwise it is
  129. * zero. The low order digit is rounded.
  130. *
  131. *Entry:
  132. * double value - number to be converted
  133. * int ndigit - number of digits after decimal point
  134. *
  135. *Exit:
  136. * returns pointer to the character representation of value.
  137. * also the output is written into the statuc char array buf.
  138. * int *decpt - pointer to int with position of decimal point
  139. * int *sign - pointer to int with sign in it (0 = pos, non-0 = neg)
  140. *
  141. *Exceptions:
  142. *
  143. *******************************************************************************/
  144. char * __cdecl _ecvt (
  145. double value,
  146. int ndigit,
  147. int *decpt,
  148. int *sign
  149. )
  150. {
  151. char *retbuf;
  152. DOUBLE *pdvalue = (DOUBLE *)&value;
  153. #ifdef _MT
  154. REG1 STRFLT pflt;
  155. struct _strflt strfltstruct; /* temporary buffers */
  156. char resultstring[21];
  157. /* ok to take address of stack struct here; fltout2 knows to use ss */
  158. pflt = _fltout2( *pdvalue, &strfltstruct, resultstring );
  159. retbuf = _fpcvt( pflt, ndigit, decpt, sign );
  160. #else
  161. retbuf = _fpcvt( _fltout(*pdvalue), ndigit, decpt, sign );
  162. #endif
  163. /* _fptostr() occasionally returns an extra character in the buffer ... */
  164. if (retbuf)
  165. if (retbuf[ndigit])
  166. retbuf[ndigit] = '\0';
  167. return( retbuf );
  168. }
  169. /***
  170. *char *_fpcvt() - gets final string and sets decpt and sign [STATIC]
  171. *
  172. *Purpose:
  173. * This is a small common routine used by [ef]cvt. It calls fptostr
  174. * to get the final string and sets the decpt and sign indicators.
  175. *
  176. *Entry:
  177. *
  178. *Exit:
  179. *
  180. *Exceptions:
  181. *
  182. *******************************************************************************/
  183. #ifdef _MT
  184. char * __cdecl _fpcvt (
  185. #else
  186. static char * __cdecl _fpcvt (
  187. #endif
  188. REG2 STRFLT pflt,
  189. REG3 int digits,
  190. int *decpt,
  191. int *sign
  192. )
  193. {
  194. #ifdef _MT
  195. /* use a per-thread buffer */
  196. char *buf;
  197. _ptiddata ptd;
  198. ptd = _getptd_noexit();
  199. if (!ptd) {
  200. return NULL;
  201. }
  202. if ( ptd->_cvtbuf == NULL )
  203. if ( (ptd->_cvtbuf = _malloc_crt(CVTBUFSIZE)) == NULL )
  204. return(NULL);
  205. buf = ptd->_cvtbuf;
  206. #endif /* _MT */
  207. /* make sure we don't overflow the buffer size. If the user asks for
  208. * more digits than the buffer can handle, truncate it to the maximum
  209. * size allowed in the buffer. The maximum size is CVTBUFSIZE - 2
  210. * since we useone character for overflow and one for the terminating
  211. * null character.
  212. */
  213. _fptostr(buf, (digits > CVTBUFSIZE - 2) ? CVTBUFSIZE - 2 : digits, pflt);
  214. /* set the sign flag and decimal point position */
  215. *sign = (pflt->sign == '-') ? 1 : 0;
  216. *decpt = pflt->decpt;
  217. return(buf);
  218. }