This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Reset xxx_convert to empty string if none of 3 utilities is found
[metaconfig.git] / U / compline / d_gconvert.U
CommitLineData
959f3c4c
JH
1?RCS: $Id: d_gconvert.U,v 3.0.1.3 1997/02/28 15:33:38 ram Exp $
2?RCS:
3?RCS: Copyright (c) 1991-1993, Raphael Manfredi
0065f4af 4?RCS:
65a32477 5?RCS: You may redistribute only under the terms of the Artistic License,
959f3c4c
JH
6?RCS: as specified in the README file that comes with the distribution.
7?RCS: You may reuse parts of this distribution only within the terms of
65a32477 8?RCS: that same Artistic License; a copy of which may be found at the root
959f3c4c
JH
9?RCS: of the source tree for dist 3.0.
10?RCS:
11?RCS: Original Author: Andy Dougherty <doughera@lafcol.lafayette.edu>
12?RCS:
13?RCS: $Log: d_gconvert.U,v $
14?RCS: Revision 3.0.1.3 1997/02/28 15:33:38 ram
15?RCS: patch61: integrated new unit from perl5
16?RCS:
17?RCS: Revision 3.0.1.2 1995/07/25 13:55:59 ram
18?RCS: patch56: improved comments about the Gconvert macro (ADO)
19?RCS: patch56: force compile-link test since it may exist but be unusable (ADO)
20?RCS:
21?RCS: Revision 3.0.1.1 1994/10/29 16:12:51 ram
22?RCS: patch36: created by ADO
23?RCS:
fd2d81e4 24?MAKE:d_Gconvert: \
70bf069f 25 Compile cat Inlibc rm _o rm_try i_stdlib d_qgcvt run \
86ff0982 26 uselongdouble d_longdbl d_PRIgldbl sPRIgldbl
959f3c4c
JH
27?MAKE: -pick add $@ %<
28?S:d_Gconvert:
29?S: This variable holds what Gconvert is defined as to convert
f8a7e493
JH
30?S: floating point numbers into strings. By default, Configure
31?S: sets this macro to use the first of gconvert, gcvt, or sprintf
65a32477 32?S: that pass sprintf-%g-like behavior tests. If perl is using
f8a7e493
JH
33?S: long doubles, the macro uses the first of the following
34?S: functions that pass Configure's tests: qgcvt, sprintf (if
35?S: Configure knows how to make sprintf format long doubles--see
2cb64bf6
MB
36?S: sPRIgldbl), gconvert, gcvt, and sprintf (casting to double).
37?S: The gconvert_preference and gconvert_ld_preference variables
f8a7e493 38?S: can be used to alter Configure's preferences, for doubles and
2cb64bf6
MB
39?S: long doubles, respectively. If present, they contain a
40?S: space-separated list of one or more of the above function
f8a7e493
JH
41?S: names in the order they should be tried.
42?S:
43?S: d_Gconvert may be set to override Configure with a platform-
44?S: specific function. If this function expects a double, a
45?S: different value may need to be set by the uselongdouble.cbu
46?S: call-back unit so that long doubles can be formatted without
47?S: loss of precision.
959f3c4c
JH
48?S:.
49?C:Gconvert:
50?C: This preprocessor macro is defined to convert a floating point
51?C: number to a string without a trailing decimal point. This
52?C: emulates the behavior of sprintf("%g"), but is sometimes much more
53?C: efficient. If gconvert() is not available, but gcvt() drops the
54?C: trailing decimal point, then gcvt() is used. If all else fails,
55?C: a macro using sprintf("%g") is used. Arguments for the Gconvert
56?C: macro are: value, number of digits, whether trailing zeros should
57?C: be retained, and the output buffer.
fd2d81e4 58?C: The usual values are:
959f3c4c
JH
59?C: d_Gconvert='gconvert((x),(n),(t),(b))'
60?C: d_Gconvert='gcvt((x),(n),(b))'
61?C: d_Gconvert='sprintf((b),"%.*g",(n),(x))'
62?C: The last two assume trailing zeros should not be kept.
63?C:.
64?H:#define Gconvert(x,n,t,b) $d_Gconvert
65?H:.
fd2d81e4 66?T: xxx_list xxx_convert xxx_ld_list
0065f4af 67?F:!try
fd2d81e4
JH
68?LINT:extern gconvert_preference
69?LINT:extern gconvert_ld_preference
959f3c4c 70: Check how to convert floats to strings.
fd2d81e4
JH
71
72if test "X$d_Gconvert" = X; then
73
de47c9df
JH
74echo " "
75echo "Checking for an efficient way to convert floats to strings."
76echo " " > try.c
77case "$uselongdouble" in
78"$define") echo "#define USE_LONG_DOUBLE" >>try.c ;;
79esac
80case "$d_longdbl" in
81"$define") echo "#define HAS_LONG_DOUBLE" >>try.c ;;
82esac
83case "$d_PRIgldbl" in
84"$define") echo "#define HAS_PRIgldbl" >>try.c ;;
85esac
86$cat >>try.c <<EOP
959f3c4c
JH
87#ifdef TRY_gconvert
88#define Gconvert(x,n,t,b) gconvert((x),(n),(t),(b))
a4702bc3 89const char *myname = "gconvert";
959f3c4c
JH
90#endif
91#ifdef TRY_gcvt
92#define Gconvert(x,n,t,b) gcvt((x),(n),(b))
a4702bc3 93const char *myname = "gcvt";
959f3c4c 94#endif
edd6115f
JH
95#ifdef TRY_qgcvt
96#define Gconvert(x,n,t,b) qgcvt((x),(n),(b))
a4702bc3 97const char *myname = "qgcvt";
65179b48 98#define DOUBLETYPE long double
edd6115f 99#endif
959f3c4c 100#ifdef TRY_sprintf
fd2d81e4
JH
101#if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE)
102#ifdef HAS_PRIgldbl
86ff0982
JH
103#define Gconvert(x,n,t,b) sprintf((b),"%.*"$sPRIgldbl,(n),(x))
104#else
fd2d81e4
JH
105#define Gconvert(x,n,t,b) sprintf((b),"%.*g",(n),(double)(x))
106#endif
107#else
959f3c4c 108#define Gconvert(x,n,t,b) sprintf((b),"%.*g",(n),(x))
86ff0982 109#endif
a4702bc3 110const char *myname = "sprintf";
959f3c4c
JH
111#endif
112
65179b48 113#ifndef DOUBLETYPE
86ff0982
JH
114#if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE)
115#define DOUBLETYPE long double
116#else
65179b48
JH
117#define DOUBLETYPE double
118#endif
86ff0982 119#endif
65179b48 120
959f3c4c
JH
121#include <stdio.h>
122
40501436 123#$i_stdlib I_STDLIB
65179b48
JH
124#ifdef I_STDLIB
125#include <stdlib.h>
126#endif
70bf069f 127#include <string.h>
65179b48 128
a4702bc3 129void checkit(const char *expect, char *got)
959f3c4c
JH
130{
131 if (strcmp(expect, got)) {
132 printf("%s oddity: Expected %s, got %s\n",
133 myname, expect, got);
134 exit(1);
135 }
136}
137
138int main()
2cb64bf6
MB
139{
140 char buf[64];
959f3c4c
JH
141 buf[63] = '\0';
142
143 /* This must be 1st test on (which?) platform */
144 /* Alan Burlison <AlanBurlsin@unn.unisys.com> */
65179b48 145 Gconvert((DOUBLETYPE)0.1, 8, 0, buf);
959f3c4c
JH
146 checkit("0.1", buf);
147
2cb64bf6 148 Gconvert((DOUBLETYPE)0.01, 8, 0, buf);
fd2d81e4
JH
149 checkit("0.01", buf);
150
2cb64bf6 151 Gconvert((DOUBLETYPE)0.001, 8, 0, buf);
fd2d81e4
JH
152 checkit("0.001", buf);
153
2cb64bf6 154 Gconvert((DOUBLETYPE)0.0001, 8, 0, buf);
fd2d81e4
JH
155 checkit("0.0001", buf);
156
157 Gconvert((DOUBLETYPE)0.00009, 8, 0, buf);
158 if (strlen(buf) > 5)
159 checkit("9e-005", buf); /* for Microsoft ?? */
160 else
161 checkit("9e-05", buf);
162
2cb64bf6 163 Gconvert((DOUBLETYPE)1.0, 8, 0, buf);
959f3c4c
JH
164 checkit("1", buf);
165
2cb64bf6 166 Gconvert((DOUBLETYPE)1.1, 8, 0, buf);
86ff0982
JH
167 checkit("1.1", buf);
168
2cb64bf6 169 Gconvert((DOUBLETYPE)1.01, 8, 0, buf);
86ff0982
JH
170 checkit("1.01", buf);
171
2cb64bf6 172 Gconvert((DOUBLETYPE)1.001, 8, 0, buf);
86ff0982
JH
173 checkit("1.001", buf);
174
2cb64bf6 175 Gconvert((DOUBLETYPE)1.0001, 8, 0, buf);
86ff0982
JH
176 checkit("1.0001", buf);
177
2cb64bf6 178 Gconvert((DOUBLETYPE)1.00001, 8, 0, buf);
86ff0982
JH
179 checkit("1.00001", buf);
180
2cb64bf6 181 Gconvert((DOUBLETYPE)1.000001, 8, 0, buf);
86ff0982
JH
182 checkit("1.000001", buf);
183
2cb64bf6 184 Gconvert((DOUBLETYPE)0.0, 8, 0, buf);
959f3c4c
JH
185 checkit("0", buf);
186
2cb64bf6 187 Gconvert((DOUBLETYPE)-1.0, 8, 0, buf);
959f3c4c
JH
188 checkit("-1", buf);
189
190 /* Some Linux gcvt's give 1.e+5 here. */
2cb64bf6 191 Gconvert((DOUBLETYPE)100000.0, 8, 0, buf);
959f3c4c 192 checkit("100000", buf);
2cb64bf6 193
959f3c4c 194 /* Some Linux gcvt's give -1.e+5 here. */
2cb64bf6 195 Gconvert((DOUBLETYPE)-100000.0, 8, 0, buf);
959f3c4c
JH
196 checkit("-100000", buf);
197
2cb64bf6 198 Gconvert((DOUBLETYPE)123.456, 8, 0, buf);
6cadf241
JH
199 checkit("123.456", buf);
200
fd2d81e4 201 /* Testing of 1e+129 in bigintpm.t must not get extra '.' here. */
f3a5eaad
JH
202 Gconvert((DOUBLETYPE)1e34, 8, 0, buf);
203 /* 34 should be enough to scare even long double
204 * places into using the e notation. */
fd2d81e4 205 if (strlen(buf) > 5)
f3a5eaad 206 checkit("1e+034", buf); /* for Microsoft */
fd2d81e4 207 else
f3a5eaad 208 checkit("1e+34", buf);
1c4981aa 209
e790fbe1
JH
210 /* For Perl, if you add additional tests here, also add them to
211 * t/base/num.t for benefit of platforms not using Configure or
212 * overriding d_Gconvert */
213
959f3c4c
JH
214 exit(0);
215}
216EOP
217?X: List of order in which to search for functions.
218?X: Usual order of efficiency is gconvert gcvt sprintf
219?X: If a hint file sets a d_Gconvert="gconvert" or "gcvt" or "sprintf",
220?X: then that is taken as a hint for which function to try first.
221?X: (e.g. that function may be in a problematic /usr/ucblib library, and
222?X: the user may or may not choose to use -lucb stuff.)
223?X: Any other hint file (or previous config.sh) setting is left intact.
fd2d81e4
JH
224: first add preferred functions to our list
225xxx_list=""
226for xxx_convert in $gconvert_preference; do
227 case $xxx_convert in
228 gcvt|gconvert|sprintf) xxx_list="$xxx_list $xxx_convert" ;;
229 *) echo "Discarding unrecognized gconvert_preference $xxx_convert" >&4 ;;
2cb64bf6 230 esac
fd2d81e4
JH
231done
232: then add any others
233for xxx_convert in gconvert gcvt sprintf; do
234 case "$xxx_list" in
235 *$xxx_convert*) ;;
236 *) xxx_list="$xxx_list $xxx_convert" ;;
2cb64bf6 237 esac
fd2d81e4 238done
de47c9df 239
fd2d81e4
JH
240case "$d_longdbl$uselongdouble" in
241"$define$define")
04c34a22 242 : again, add preferred functions to our list first
fd2d81e4
JH
243 xxx_ld_list=""
244 for xxx_convert in $gconvert_ld_preference; do
245 case $xxx_convert in
246 qgcvt|gcvt|gconvert|sprintf) xxx_ld_list="$xxx_ld_list $xxx_convert" ;;
247 *) echo "Discarding unrecognized gconvert_ld_preference $xxx_convert" ;;
248 esac
249 done
250 : then add qgcvt, sprintf--then, in xxx_list order, gconvert and gcvt
251 for xxx_convert in qgcvt sprintf $xxx_list; do
252 case "$xxx_ld_list" in
253 $xxx_convert*|*" $xxx_convert"*) ;;
254 *) xxx_ld_list="$xxx_ld_list $xxx_convert" ;;
255 esac
256 done
257 : if sprintf cannot do long doubles, move it to the end
258 if test "$d_PRIgldbl" != "$define"; then
259 xxx_ld_list="`echo $xxx_ld_list|sed s/sprintf//` sprintf"
260 fi
261 : if no qgcvt, remove it
262 if test "$d_qgcvt" != "$define"; then
263 xxx_ld_list="`echo $xxx_ld_list|sed s/qgcvt//`"
264 fi
265 : use the ld_list
266 xxx_list="$xxx_ld_list"
de47c9df
JH
267 ;;
268esac
269
270for xxx_convert in $xxx_list; do
271 echo "Trying $xxx_convert..."
3fb5973e
MB
272?X: Do NOT use $rm_try here, as we need to keep try.c
273 $rm -f try try$_o core
de47c9df
JH
274 set try -DTRY_$xxx_convert
275 if eval $compile; then
276 echo "$xxx_convert() found." >&4
0f00356b 277 if $run ./try; then
de47c9df
JH
278 echo "I'll use $xxx_convert to convert floats into a string." >&4
279 break;
959f3c4c 280 else
de47c9df 281 echo "...But $xxx_convert didn't work as I expected."
fd2d81e4 282 xxx_convert=''
959f3c4c 283 fi
de47c9df
JH
284 else
285 echo "$xxx_convert NOT found." >&4
a4702bc3 286 xxx_convert=''
de47c9df
JH
287 fi
288done
fd2d81e4
JH
289
290if test X$xxx_convert = X; then
291 echo "*** WHOA THERE!!! ***" >&4
292 echo "None of ($xxx_list) seemed to work properly. I'll use sprintf." >&4
293 xxx_convert=sprintf
294fi
295
de47c9df
JH
296case "$xxx_convert" in
297gconvert) d_Gconvert='gconvert((x),(n),(t),(b))' ;;
298gcvt) d_Gconvert='gcvt((x),(n),(b))' ;;
299qgcvt) d_Gconvert='qgcvt((x),(n),(b))' ;;
300*) case "$uselongdouble$d_longdbl$d_PRIgldbl" in
301 "$define$define$define")
8208ea90 302 d_Gconvert="sprintf((b),\"%.*\"$sPRIgldbl,(n),(x))" ;;
fd2d81e4
JH
303 "$define$define$undef")
304 d_Gconvert='sprintf((b),"%.*g",(n),(double)(x))' ;;
de47c9df
JH
305 *) d_Gconvert='sprintf((b),"%.*g",(n),(x))' ;;
306 esac
2cb64bf6 307 ;;
de47c9df 308esac
959f3c4c 309
fd2d81e4 310fi
3fb5973e 311$rm_try
fd2d81e4 312