Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtksh / ksh93 / src / lib / libast / sfio / sfcvt.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: sfcvt.c /main/3 1995/11/01 18:27:35 rswiston $ */
24 /***************************************************************
25 *                                                              *
26 *                      AT&T - PROPRIETARY                      *
27 *                                                              *
28 *         THIS IS PROPRIETARY SOURCE CODE LICENSED BY          *
29 *                          AT&T CORP.                          *
30 *                                                              *
31 *                Copyright (c) 1995 AT&T Corp.                 *
32 *                     All Rights Reserved                      *
33 *                                                              *
34 *           This software is licensed by AT&T Corp.            *
35 *       under the terms and conditions of the license in       *
36 *       http://www.research.att.com/orgs/ssr/book/reuse        *
37 *                                                              *
38 *               This software was created by the               *
39 *           Software Engineering Research Department           *
40 *                    AT&T Bell Laboratories                    *
41 *                                                              *
42 *               For further information contact                *
43 *                     gsf@research.att.com                     *
44 *                                                              *
45 ***************************************************************/
46 #include        "sfhdr.h"
47
48 /*      Convert a floating point value to ASCII
49 **      This function unifies fcvt() and ecvt() in libc.a.
50 **
51 **      Written by Kiem-Phong Vo (06/27/90)
52 */
53
54 static char     *Inf = "Inf", *Zero = "0";
55 #define INTPART         (SF_IDIGITS/2)
56 #define INFINITE        ((_Sfi = 3), Inf)
57 #define ZERO            ((_Sfi = 1), Zero)
58
59 #if !_sfio_cvt
60 _BEGIN_EXTERNS_
61 extern char*    fcvt _ARG_((Double_t,int,int*,int*));
62 extern char*    ecvt _ARG_((Double_t,int,int*,int*));
63 _END_EXTERNS_
64 #endif
65
66 #if __STD_C
67 char* _sfcvt(Double_t dval, int n_digit, int* decpt, int* sign, int e_format)
68 #else
69 char* _sfcvt(dval,n_digit,decpt,sign,e_format)
70 Double_t        dval;           /* value to convert */
71 int             n_digit;        /* number of digits wanted */
72 int*            decpt;          /* to return decimal point */
73 int*            sign;           /* to return sign */
74 int             e_format;       /* doing e-format */
75 #endif
76 {
77 #if !_sfio_cvt
78         reg char*       sp;
79         sp = e_format ? ecvt(dval,n_digit,decpt,sign) : fcvt(dval,n_digit,decpt,sign);
80         _Sfi = strlen(sp);
81         return sp;
82 #else
83         reg long        n, v;
84         reg char        *sp, *ep, *buf, *endsp;
85         static char     *Buf;
86
87         /* set up local buffer */
88         if(!Buf && !(Buf = (char*)malloc(SF_MAXDIGITS)))
89                 return INFINITE;
90
91         *sign = *decpt = 0;
92         if(dval == 0.)
93                 return ZERO;
94         else if(*sign = (dval < 0.))    /* assignment = */
95                 dval = -dval;
96
97         n = 0;
98         if(dval >= (Double_t)SF_MAXLONG)
99         {       /* scale to a small enough number to fit an int */
100                 v = SF_MAXEXP10-1;
101                 do
102                 {       if(dval < _Sfpos10[v])
103                                 v -= 1;
104                         else
105                         {
106                                 dval *= _Sfneg10[v];
107                                 if((n += (1<<v)) >= SF_IDIGITS)
108                                         return INFINITE;
109                         }
110                 } while(dval >= (Double_t)SF_MAXLONG);
111         }
112         *decpt = (int)n;
113
114         buf = sp = Buf+INTPART;
115         if((v = (int)dval) != 0)
116         {       /* translate the integer part */
117                 dval -= (Double_t)v;
118
119                 sfucvt(v,sp,n,ep);
120
121                 n = buf-sp;
122                 if((*decpt += (int)n) >= SF_IDIGITS)
123                         return INFINITE;
124                 buf = sp;
125                 sp = Buf+INTPART;
126         }
127         else    n = 0;
128
129         /* remaining number of digits to compute; add 1 for later rounding */
130         n = ((e_format || *decpt <= 0) ? 1 : *decpt+1) - n;
131         if(n_digit > 0)
132                 n += n_digit;
133
134         if((ep = (sp+n)) > (endsp = Buf+(SF_MAXDIGITS-2)))
135                 ep = endsp; 
136         if(sp > ep)
137                 sp = ep;
138         else while(sp < ep)
139         {       /* generate fractional digits */
140                 if(dval <= 0.)
141                 {       /* fill with 0's */
142                         do { *sp++ = '0'; } while(sp < ep);
143                         goto done;
144                 }
145                 *sp++ = (char)('0' + (n = (int)(dval *= 10.)));
146                 dval -= (Double_t)n;
147         }
148
149         if(ep <= buf)
150                 ep = buf+1;
151         else if(ep < endsp)
152         {       /* round the last digit */
153                 *--sp += 5;
154                 while(*sp > '9')
155                 {
156                         *sp = '0';
157                         if(sp > buf)
158                                 *--sp += 1;
159                         else
160                         {       /* next power of 10 */
161                                 *sp = '1';
162                                 *decpt += 1;
163                                 if(!e_format)
164                                 {       /* add one more 0 for %f precision */
165                                         ep[-1] = '0';
166                                         ep += 1;
167                                 }
168                         }
169                 }
170         }
171
172 done:
173         *--ep = '\0';
174         _Sfi = ep-buf;
175         return buf;
176
177 #endif /* !_sfio_cvt */
178 }