Guard against vsnprintf implementations that mishandle a size=0 argument.
[gnulib.git] / m4 / printf.m4
1 # printf.m4 serial 7
2 dnl Copyright (C) 2003, 2007 Free Software Foundation, Inc.
3 dnl This file is free software; the Free Software Foundation
4 dnl gives unlimited permission to copy and/or distribute it,
5 dnl with or without modifications, as long as this notice is preserved.
6
7 dnl Test whether the *printf family of functions supports the 'j', 'z', 't',
8 dnl 'L' size specifiers. (ISO C99, POSIX:2001)
9 dnl Result is gl_cv_func_printf_sizes_c99.
10
11 AC_DEFUN([gl_PRINTF_SIZES_C99],
12 [
13   AC_REQUIRE([AC_PROG_CC])
14   AC_REQUIRE([gl_AC_HEADER_STDINT_H])
15   AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
16   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
17   AC_CACHE_CHECK([whether printf supports size specifiers as in C99],
18     [gl_cv_func_printf_sizes_c99], 
19     [
20       AC_TRY_RUN([
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #if HAVE_STDINT_H_WITH_UINTMAX
26 # include <stdint.h>
27 #endif
28 #if HAVE_INTTYPES_H_WITH_UINTMAX
29 # include <inttypes.h>
30 #endif
31 static char buf[100];
32 int main ()
33 {
34 #if HAVE_STDINT_H_WITH_UINTMAX || HAVE_INTTYPES_H_WITH_UINTMAX
35   buf[0] = '\0';
36   if (sprintf (buf, "%ju %d", (uintmax_t) 12345671, 33, 44, 55) < 0
37       || strcmp (buf, "12345671 33") != 0)
38     return 1;
39 #endif
40   buf[0] = '\0';
41   if (sprintf (buf, "%zu %d", (size_t) 12345672, 33, 44, 55) < 0
42       || strcmp (buf, "12345672 33") != 0)
43     return 1;
44   buf[0] = '\0';
45   if (sprintf (buf, "%tu %d", (ptrdiff_t) 12345673, 33, 44, 55) < 0
46       || strcmp (buf, "12345673 33") != 0)
47     return 1;
48   buf[0] = '\0';
49   if (sprintf (buf, "%Lg %d", (long double) 1.5, 33, 44, 55) < 0
50       || strcmp (buf, "1.5 33") != 0)
51     return 1;
52   return 0;
53 }], [gl_cv_func_printf_sizes_c99=yes], [gl_cv_func_printf_sizes_c99=no],
54       [
55 changequote(,)dnl
56        case "$host_os" in
57                                # Guess yes on glibc systems.
58          *-gnu*)               gl_cv_func_printf_sizes_c99="guessing yes";;
59                                # Guess yes on FreeBSD >= 5.
60          freebsd[1-4]*)        gl_cv_func_printf_sizes_c99="guessing no";;
61          freebsd* | kfreebsd*) gl_cv_func_printf_sizes_c99="guessing yes";;
62                                # Guess yes on MacOS X >= 10.3.
63          darwin[1-6].*)        gl_cv_func_printf_sizes_c99="guessing no";;
64          darwin*)              gl_cv_func_printf_sizes_c99="guessing yes";;
65                                # Guess yes on OpenBSD >= 3.9.
66          openbsd[1-2].* | openbsd3.[0-8] | openbsd3.[0-8].*)
67                                gl_cv_func_printf_sizes_c99="guessing no";;
68          openbsd*)             gl_cv_func_printf_sizes_c99="guessing yes";;
69                                # Guess yes on Solaris >= 2.10.
70          solaris2.[0-9]*)      gl_cv_func_printf_sizes_c99="guessing no";;
71          solaris*)             gl_cv_func_printf_sizes_c99="guessing yes";;
72                                # Guess yes on NetBSD >= 3.
73          netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
74                                gl_cv_func_printf_sizes_c99="guessing no";;
75          netbsd*)              gl_cv_func_printf_sizes_c99="guessing yes";;
76                                # If we don't know, assume the worst.
77          *)                    gl_cv_func_printf_sizes_c99="guessing no";;
78        esac
79 changequote([,])dnl
80       ])
81     ])
82 ])
83
84 dnl Test whether the *printf family of functions supports the 'a' and 'A'
85 dnl conversion specifier for hexadecimal output of floating-point numbers.
86 dnl (ISO C99, POSIX:2001)
87 dnl Result is gl_cv_func_printf_directive_a.
88
89 AC_DEFUN([gl_PRINTF_DIRECTIVE_A],
90 [
91   AC_REQUIRE([AC_PROG_CC])
92   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
93   AC_CACHE_CHECK([whether printf supports the 'a' and 'A' directives],
94     [gl_cv_func_printf_directive_a], 
95     [
96       AC_TRY_RUN([
97 #include <stdio.h>
98 #include <string.h>
99 static char buf[100];
100 int main ()
101 {
102   if (sprintf (buf, "%a %d", 3.1416015625, 33, 44, 55) < 0
103       || (strcmp (buf, "0x1.922p+1 33") != 0
104           && strcmp (buf, "0x3.244p+0 33") != 0
105           && strcmp (buf, "0x6.488p-1 33") != 0
106           && strcmp (buf, "0xc.91p-2 33") != 0))
107     return 1;
108   if (sprintf (buf, "%A %d", -3.1416015625, 33, 44, 55) < 0
109       || (strcmp (buf, "-0X1.922P+1 33") != 0
110           && strcmp (buf, "-0X3.244P+0 33") != 0
111           && strcmp (buf, "-0X6.488P-1 33") != 0
112           && strcmp (buf, "-0XC.91P-2 33") != 0))
113     return 1;
114   /* This catches a FreeBSD 6.1 bug: it doesn't round.  */
115   if (sprintf (buf, "%.2a %d", 1.51, 33, 44, 55) < 0
116       || (strcmp (buf, "0x1.83p+0 33") != 0
117           && strcmp (buf, "0x3.05p-1 33") != 0
118           && strcmp (buf, "0x6.0ap-2 33") != 0
119           && strcmp (buf, "0xc.14p-3 33") != 0))
120     return 1;
121   /* This catches a FreeBSD 6.1 bug.  See
122      <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
123   if (sprintf (buf, "%010a %d", 1.0 / 0.0, 33, 44, 55) < 0
124       || buf[0] == '0')
125     return 1;
126   /* This catches a MacOS X 10.3.9 (Darwin 7.9) bug.  */
127   if (sprintf (buf, "%.1a", 1.999) < 0
128       || (strcmp (buf, "0x1.0p+1") != 0
129           && strcmp (buf, "0x2.0p+0") != 0
130           && strcmp (buf, "0x4.0p-1") != 0
131           && strcmp (buf, "0x8.0p-2") != 0))
132     return 1;
133   /* This catches the same MacOS X 10.3.9 (Darwin 7.9) bug and also a
134      glibc 2.4 bug <http://sourceware.org/bugzilla/show_bug.cgi?id=2908>.  */
135   if (sprintf (buf, "%.1La", 1.999L) < 0
136       || (strcmp (buf, "0x1.0p+1") != 0
137           && strcmp (buf, "0x2.0p+0") != 0
138           && strcmp (buf, "0x4.0p-1") != 0
139           && strcmp (buf, "0x8.0p-2") != 0))
140     return 1;
141   return 0;
142 }], [gl_cv_func_printf_directive_a=yes], [gl_cv_func_printf_directive_a=no],
143       [
144        case "$host_os" in
145                                # Guess yes on glibc >= 2.5 systems.
146          *-gnu*)
147            AC_EGREP_CPP([BZ2908], [
148              #include <features.h>
149              #ifdef __GNU_LIBRARY__
150               #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 5) || (__GLIBC__ > 2)
151                BZ2908
152               #endif
153              #endif
154              ],
155              [gl_cv_func_printf_directive_a="guessing yes"],
156              [gl_cv_func_printf_directive_a="guessing no"])
157            ;;
158                                # If we don't know, assume the worst.
159          *)                    gl_cv_func_printf_directive_a="guessing no";;
160        esac
161       ])
162     ])
163 ])
164
165 dnl Test whether the *printf family of functions supports the %F format
166 dnl directive. (ISO C99, POSIX:2001)
167 dnl Result is gl_cv_func_printf_directive_f.
168
169 AC_DEFUN([gl_PRINTF_DIRECTIVE_F],
170 [
171   AC_REQUIRE([AC_PROG_CC])
172   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
173   AC_CACHE_CHECK([whether printf supports the 'F' directive],
174     [gl_cv_func_printf_directive_f], 
175     [
176       AC_TRY_RUN([
177 #include <stdio.h>
178 #include <string.h>
179 static char buf[100];
180 int main ()
181 {
182   if (sprintf (buf, "%F %d", 1234567.0, 33, 44, 55) < 0
183       || strcmp (buf, "1234567.000000 33") != 0)
184     return 1;
185   if (sprintf (buf, "%F", 1.0 / 0.0) < 0
186       || (strcmp (buf, "INF") != 0 && strcmp (buf, "INFINITY") != 0))
187     return 1;
188   /* This catches a Cygwin 2007 bug.  */
189   if (sprintf (buf, "%.F", 1234.0) < 0
190       || strcmp (buf, "1234") != 0)
191     return 1;
192   return 0;
193 }], [gl_cv_func_printf_directive_f=yes], [gl_cv_func_printf_directive_f=no],
194       [
195 changequote(,)dnl
196        case "$host_os" in
197                                # Guess yes on glibc systems.
198          *-gnu*)               gl_cv_func_printf_directive_f="guessing yes";;
199                                # Guess yes on FreeBSD >= 6.
200          freebsd[1-5]*)        gl_cv_func_printf_directive_f="guessing no";;
201          freebsd* | kfreebsd*) gl_cv_func_printf_directive_f="guessing yes";;
202                                # Guess yes on MacOS X >= 10.3.
203          darwin[1-6].*)        gl_cv_func_printf_directive_f="guessing no";;
204          darwin*)              gl_cv_func_printf_directive_f="guessing yes";;
205                                # Guess yes on Solaris >= 2.10.
206          solaris2.[0-9]*)      gl_cv_func_printf_directive_f="guessing no";;
207          solaris*)             gl_cv_func_printf_directive_f="guessing yes";;
208                                # If we don't know, assume the worst.
209          *)                    gl_cv_func_printf_directive_f="guessing no";;
210        esac
211 changequote([,])dnl
212       ])
213     ])
214 ])
215
216 dnl Test whether the *printf family of functions supports the %n format
217 dnl directive. (ISO C99, POSIX:2001)
218 dnl Result is gl_cv_func_printf_directive_n.
219
220 AC_DEFUN([gl_PRINTF_DIRECTIVE_N],
221 [
222   AC_REQUIRE([AC_PROG_CC])
223   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
224   AC_CACHE_CHECK([whether printf supports the 'n' directive],
225     [gl_cv_func_printf_directive_n], 
226     [
227       AC_TRY_RUN([
228 #include <stdio.h>
229 #include <string.h>
230 static char buf[100];
231 int main ()
232 {
233   int count = -1;
234   if (sprintf (buf, "%d %n", 123, &count, 33, 44, 55) < 0
235       || strcmp (buf, "123 ") != 0
236       || count != 4)
237     return 1;
238   return 0;
239 }], [gl_cv_func_printf_directive_n=yes], [gl_cv_func_printf_directive_n=no],
240       [
241 changequote(,)dnl
242        case "$host_os" in
243          *)     gl_cv_func_printf_directive_n="guessing yes";;
244        esac
245 changequote([,])dnl
246       ])
247     ])
248 ])
249
250 dnl Test whether the *printf family of functions supports POSIX/XSI format
251 dnl strings with positions. (POSIX:2001)
252 dnl Result is gl_cv_func_printf_positions.
253
254 AC_DEFUN([gl_PRINTF_POSITIONS],
255 [
256   AC_REQUIRE([AC_PROG_CC])
257   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
258   AC_CACHE_CHECK([whether printf supports POSIX/XSI format strings with positions],
259     [gl_cv_func_printf_positions], 
260     [
261       AC_TRY_RUN([
262 #include <stdio.h>
263 #include <string.h>
264 /* The string "%2$d %1$d", with dollar characters protected from the shell's
265    dollar expansion (possibly an autoconf bug).  */
266 static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' };
267 static char buf[100];
268 int main ()
269 {
270   sprintf (buf, format, 33, 55);
271   return (strcmp (buf, "55 33") != 0);
272 }], [gl_cv_func_printf_positions=yes], [gl_cv_func_printf_positions=no],
273       [
274 changequote(,)dnl
275        case "$host_os" in
276          netbsd[1-3]* | netbsdelf[1-3]* | netbsdaout[1-3]* | netbsdcoff[1-3]*)
277                        gl_cv_func_printf_positions="guessing no";;
278          beos*)        gl_cv_func_printf_positions="guessing no";;
279          mingw* | pw*) gl_cv_func_printf_positions="guessing no";;
280          *)            gl_cv_func_printf_positions="guessing yes";;
281        esac
282 changequote([,])dnl
283       ])
284     ])
285 ])
286
287 dnl Test whether the snprintf function exists. (ISO C99, POSIX:2001)
288 dnl Result is ac_cv_func_snprintf.
289
290 AC_DEFUN([gl_SNPRINTF_PRESENCE],
291 [
292   AC_CHECK_FUNCS_ONCE([snprintf])
293 ])
294
295 dnl Test whether the string produced by the snprintf function is always NUL
296 dnl terminated. (ISO C99, POSIX:2001)
297 dnl Result is gl_cv_func_snprintf_truncation_c99.
298
299 AC_DEFUN([gl_SNPRINTF_TRUNCATION_C99],
300 [
301   AC_REQUIRE([AC_PROG_CC])
302   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
303   AC_CACHE_CHECK([whether snprintf truncates the result as in C99],
304     [gl_cv_func_snprintf_truncation_c99], 
305     [
306       AC_TRY_RUN([
307 #include <stdio.h>
308 #include <string.h>
309 static char buf[100];
310 int main ()
311 {
312   strcpy (buf, "ABCDEF");
313   snprintf (buf, 3, "%d %d", 4567, 89);
314   if (memcmp (buf, "45\0DEF", 6) != 0)
315     return 1;
316   return 0;
317 }], [gl_cv_func_snprintf_truncation_c99=yes], [gl_cv_func_snprintf_truncation_c99=no],
318       [
319 changequote(,)dnl
320        case "$host_os" in
321                                # Guess yes on glibc systems.
322          *-gnu*)               gl_cv_func_snprintf_truncation_c99="guessing yes";;
323                                # Guess yes on FreeBSD >= 5.
324          freebsd[1-4]*)        gl_cv_func_snprintf_truncation_c99="guessing no";;
325          freebsd* | kfreebsd*) gl_cv_func_snprintf_truncation_c99="guessing yes";;
326                                # Guess yes on MacOS X >= 10.3.
327          darwin[1-6].*)        gl_cv_func_snprintf_truncation_c99="guessing no";;
328          darwin*)              gl_cv_func_snprintf_truncation_c99="guessing yes";;
329                                # Guess yes on OpenBSD >= 3.9.
330          openbsd[1-2].* | openbsd3.[0-8] | openbsd3.[0-8].*)
331                                gl_cv_func_snprintf_truncation_c99="guessing no";;
332          openbsd*)             gl_cv_func_snprintf_truncation_c99="guessing yes";;
333                                # Guess yes on Solaris >= 2.6.
334          solaris2.[0-5]*)      gl_cv_func_snprintf_truncation_c99="guessing no";;
335          solaris*)             gl_cv_func_snprintf_truncation_c99="guessing yes";;
336                                # Guess yes on AIX >= 4.
337          aix[1-3]*)            gl_cv_func_snprintf_truncation_c99="guessing no";;
338          aix*)                 gl_cv_func_snprintf_truncation_c99="guessing yes";;
339                                # Guess yes on HP-UX >= 11.
340          hpux[7-9]* | hpux10*) gl_cv_func_snprintf_truncation_c99="guessing no";;
341          hpux*)                gl_cv_func_snprintf_truncation_c99="guessing yes";;
342                                # Guess yes on IRIX >= 6.5.
343          irix6.5)              gl_cv_func_snprintf_truncation_c99="guessing yes";;
344                                # Guess yes on OSF/1 >= 5.
345          osf[3-4]*)            gl_cv_func_snprintf_truncation_c99="guessing no";;
346          osf*)                 gl_cv_func_snprintf_truncation_c99="guessing yes";;
347                                # Guess yes on NetBSD >= 3.
348          netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
349                                gl_cv_func_snprintf_truncation_c99="guessing no";;
350          netbsd*)              gl_cv_func_snprintf_truncation_c99="guessing yes";;
351                                # Guess yes on BeOS.
352          beos*)                gl_cv_func_snprintf_truncation_c99="guessing yes";;
353                                # If we don't know, assume the worst.
354          *)                    gl_cv_func_snprintf_truncation_c99="guessing no";;
355        esac
356 changequote([,])dnl
357       ])
358     ])
359 ])
360
361 dnl Test whether the return value of the snprintf function is the number
362 dnl of bytes (excluding the terminating NUL) that would have been produced
363 dnl if the buffer had been large enough. (ISO C99, POSIX:2001)
364 dnl For example, this test program fails on IRIX 6.5:
365 dnl     ---------------------------------------------------------------------
366 dnl     #include <stdio.h>
367 dnl     int main()
368 dnl     {
369 dnl       static char buf[8];
370 dnl       int retval = snprintf (buf, 3, "%d", 12345);
371 dnl       return retval >= 0 && retval < 3;
372 dnl     }
373 dnl     ---------------------------------------------------------------------
374 dnl Result is gl_cv_func_snprintf_retval_c99.
375
376 AC_DEFUN([gl_SNPRINTF_RETVAL_C99],
377 [
378   AC_REQUIRE([AC_PROG_CC])
379   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
380   AC_CACHE_CHECK([whether snprintf returns a byte count as in C99],
381     [gl_cv_func_snprintf_retval_c99], 
382     [
383       AC_TRY_RUN([
384 #include <stdio.h>
385 #include <string.h>
386 static char buf[100];
387 int main ()
388 {
389   strcpy (buf, "ABCDEF");
390   if (snprintf (buf, 3, "%d %d", 4567, 89) != 7)
391     return 1;
392   return 0;
393 }], [gl_cv_func_snprintf_retval_c99=yes], [gl_cv_func_snprintf_retval_c99=no],
394       [
395 changequote(,)dnl
396        case "$host_os" in
397                                # Guess yes on glibc systems.
398          *-gnu*)               gl_cv_func_snprintf_retval_c99="guessing yes";;
399                                # Guess yes on FreeBSD >= 5.
400          freebsd[1-4]*)        gl_cv_func_snprintf_retval_c99="guessing no";;
401          freebsd* | kfreebsd*) gl_cv_func_snprintf_retval_c99="guessing yes";;
402                                # Guess yes on MacOS X >= 10.3.
403          darwin[1-6].*)        gl_cv_func_snprintf_retval_c99="guessing no";;
404          darwin*)              gl_cv_func_snprintf_retval_c99="guessing yes";;
405                                # Guess yes on OpenBSD >= 3.9.
406          openbsd[1-2].* | openbsd3.[0-8] | openbsd3.[0-8].*)
407                                gl_cv_func_snprintf_retval_c99="guessing no";;
408          openbsd*)             gl_cv_func_snprintf_retval_c99="guessing yes";;
409                                # Guess yes on Solaris >= 2.6.
410          solaris2.[0-5]*)      gl_cv_func_snprintf_retval_c99="guessing no";;
411          solaris*)             gl_cv_func_snprintf_retval_c99="guessing yes";;
412                                # Guess yes on AIX >= 4.
413          aix[1-3]*)            gl_cv_func_snprintf_retval_c99="guessing no";;
414          aix*)                 gl_cv_func_snprintf_retval_c99="guessing yes";;
415                                # Guess yes on NetBSD >= 3.
416          netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
417                                gl_cv_func_snprintf_retval_c99="guessing no";;
418          netbsd*)              gl_cv_func_snprintf_retval_c99="guessing yes";;
419                                # Guess yes on BeOS.
420          beos*)                gl_cv_func_snprintf_retval_c99="guessing yes";;
421                                # If we don't know, assume the worst.
422          *)                    gl_cv_func_snprintf_retval_c99="guessing no";;
423        esac
424 changequote([,])dnl
425       ])
426     ])
427 ])
428
429 dnl Test whether the snprintf function supports the %n format directive
430 dnl also in truncated portions of the format string. (ISO C99, POSIX:2001)
431 dnl Result is gl_cv_func_snprintf_directive_n.
432
433 AC_DEFUN([gl_SNPRINTF_DIRECTIVE_N],
434 [
435   AC_REQUIRE([AC_PROG_CC])
436   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
437   AC_CACHE_CHECK([whether snprintf fully supports the 'n' directive],
438     [gl_cv_func_snprintf_directive_n], 
439     [
440       AC_TRY_RUN([
441 #include <stdio.h>
442 #include <string.h>
443 static char buf[100];
444 int main ()
445 {
446   int count = -1;
447   snprintf (buf, 4, "%d %n", 12345, &count, 33, 44, 55);
448   if (count != 6)
449     return 1;
450   return 0;
451 }], [gl_cv_func_snprintf_directive_n=yes], [gl_cv_func_snprintf_directive_n=no],
452       [
453 changequote(,)dnl
454        case "$host_os" in
455                                # Guess yes on glibc systems.
456          *-gnu*)               gl_cv_func_snprintf_directive_n="guessing yes";;
457                                # Guess yes on FreeBSD >= 5.
458          freebsd[1-4]*)        gl_cv_func_snprintf_directive_n="guessing no";;
459          freebsd* | kfreebsd*) gl_cv_func_snprintf_directive_n="guessing yes";;
460                                # Guess yes on MacOS X >= 10.3.
461          darwin[1-6].*)        gl_cv_func_snprintf_directive_n="guessing no";;
462          darwin*)              gl_cv_func_snprintf_directive_n="guessing yes";;
463                                # Guess yes on Solaris >= 2.6.
464          solaris2.[0-5]*)      gl_cv_func_snprintf_directive_n="guessing no";;
465          solaris*)             gl_cv_func_snprintf_directive_n="guessing yes";;
466                                # Guess yes on AIX >= 4.
467          aix[1-3]*)            gl_cv_func_snprintf_directive_n="guessing no";;
468          aix*)                 gl_cv_func_snprintf_directive_n="guessing yes";;
469                                # Guess yes on IRIX >= 6.5.
470          irix6.5)              gl_cv_func_snprintf_directive_n="guessing yes";;
471                                # Guess yes on OSF/1 >= 5.
472          osf[3-4]*)            gl_cv_func_snprintf_directive_n="guessing no";;
473          osf*)                 gl_cv_func_snprintf_directive_n="guessing yes";;
474                                # Guess yes on NetBSD >= 3.
475          netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
476                                gl_cv_func_snprintf_directive_n="guessing no";;
477          netbsd*)              gl_cv_func_snprintf_directive_n="guessing yes";;
478                                # Guess yes on BeOS.
479          beos*)                gl_cv_func_snprintf_directive_n="guessing yes";;
480                                # If we don't know, assume the worst.
481          *)                    gl_cv_func_snprintf_directive_n="guessing no";;
482        esac
483 changequote([,])dnl
484       ])
485     ])
486 ])
487
488 dnl Test whether the vsnprintf function, when passed a zero size, produces no
489 dnl output. (ISO C99, POSIX:2001)
490 dnl For example, snprintf nevertheless writes a NUL byte in this case
491 dnl on OSF/1 5.1:
492 dnl     ---------------------------------------------------------------------
493 dnl     #include <stdio.h>
494 dnl     int main()
495 dnl     {
496 dnl       static char buf[8] = "DEADBEEF";
497 dnl       snprintf (buf, 0, "%d", 12345);
498 dnl       return buf[0] != 'D';
499 dnl     }
500 dnl     ---------------------------------------------------------------------
501 dnl And vsnprintf writes any output without bounds in this case, behaving like
502 dnl vsprintf, on HP-UX 11 and OSF/1 5.1:
503 dnl     ---------------------------------------------------------------------
504 dnl     #include <stdarg.h>
505 dnl     #include <stdio.h>
506 dnl     static int my_snprintf (char *buf, int size, const char *format, ...)
507 dnl     {
508 dnl       va_list args;
509 dnl       int ret;
510 dnl       va_start (args, format);
511 dnl       ret = vsnprintf (buf, size, format, args);
512 dnl       va_end (args);
513 dnl       return ret;
514 dnl     }
515 dnl     int main()
516 dnl     {
517 dnl       static char buf[8] = "DEADBEEF";
518 dnl       my_snprintf (buf, 0, "%d", 12345);
519 dnl       return buf[0] != 'D';
520 dnl     }
521 dnl     ---------------------------------------------------------------------
522 dnl Result is gl_cv_func_vsnprintf_zerosize_c99.
523
524 AC_DEFUN([gl_VSNPRINTF_ZEROSIZE_C99],
525 [
526   AC_REQUIRE([AC_PROG_CC])
527   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
528   AC_CACHE_CHECK([whether vsnprintf respects a zero size as in C99],
529     [gl_cv_func_vsnprintf_zerosize_c99], 
530     [
531       AC_TRY_RUN([
532 #include <stdarg.h>
533 #include <stdio.h>
534 static int my_snprintf (char *buf, int size, const char *format, ...)
535 {
536   va_list args;
537   int ret;
538   va_start (args, format);
539   ret = vsnprintf (buf, size, format, args);
540   va_end (args);
541   return ret;
542 }
543 int main()
544 {
545   static char buf[8] = "DEADBEEF";
546   my_snprintf (buf, 0, "%d", 12345);
547   return buf[0] != 'D';
548 }],
549       [gl_cv_func_vsnprintf_zerosize_c99=yes],
550       [gl_cv_func_vsnprintf_zerosize_c99=no],
551       [
552 changequote(,)dnl
553        case "$host_os" in
554                                # Guess yes on glibc systems.
555          *-gnu*)               gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
556                                # Guess yes on FreeBSD >= 5.
557          freebsd[1-4]*)        gl_cv_func_vsnprintf_zerosize_c99="guessing no";;
558          freebsd* | kfreebsd*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
559                                # Guess yes on MacOS X >= 10.3.
560          darwin[1-6].*)        gl_cv_func_vsnprintf_zerosize_c99="guessing no";;
561          darwin*)              gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
562                                # Guess yes on Solaris >= 2.6.
563          solaris2.[0-5]*)      gl_cv_func_vsnprintf_zerosize_c99="guessing no";;
564          solaris*)             gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
565                                # Guess yes on AIX >= 4.
566          aix[1-3]*)            gl_cv_func_vsnprintf_zerosize_c99="guessing no";;
567          aix*)                 gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
568                                # Guess yes on IRIX >= 6.5.
569          irix6.5)              gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
570                                # Guess yes on NetBSD >= 3.
571          netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
572                                gl_cv_func_vsnprintf_zerosize_c99="guessing no";;
573          netbsd*)              gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
574                                # Guess yes on BeOS.
575          beos*)                gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
576                                # Guess yes on mingw.
577          mingw* | pw*)         gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
578                                # If we don't know, assume the worst.
579          *)                    gl_cv_func_vsnprintf_zerosize_c99="guessing no";;
580        esac
581 changequote([,])dnl
582       ])
583     ])
584 ])
585
586 dnl The results of these tests on various platforms are:
587 dnl
588 dnl 1 = gl_PRINTF_SIZES_C99
589 dnl 2 = gl_PRINTF_DIRECTIVE_A
590 dnl 3 = gl_PRINTF_DIRECTIVE_F
591 dnl 4 = gl_PRINTF_DIRECTIVE_N
592 dnl 5 = gl_PRINTF_POSITIONS
593 dnl 6 = gl_SNPRINTF_PRESENCE
594 dnl 7 = gl_SNPRINTF_TRUNCATION_C99
595 dnl 8 = gl_SNPRINTF_RETVAL_C99
596 dnl 9 = gl_SNPRINTF_DIRECTIVE_N
597 dnl 10 = gl_VSNPRINTF_ZEROSIZE_C99
598 dnl
599 dnl 1 = checking whether printf supports size specifiers as in C99...
600 dnl 2 = checking whether printf supports the 'a' and 'A' directives...
601 dnl 3 = checking whether printf supports the 'F' directive...
602 dnl 4 = checking whether printf supports the 'n' directive...
603 dnl 5 = checking whether printf supports POSIX/XSI format strings with positions...
604 dnl 6 = checking for snprintf...
605 dnl 7 = checking whether snprintf truncates the result as in C99...
606 dnl 8 = checking whether snprintf returns a byte count as in C99...
607 dnl 9 = checking whether snprintf fully supports the 'n' directive...
608 dnl 10 = checking whether vsnprintf respects a zero size as in C99...
609 dnl
610 dnl . = yes, # = no.
611 dnl
612 dnl                                        1  2  3  4  5  6  7  8  9 10
613 dnl   glibc 2.5                            .  .  .  .  .  .  .  .  .  .
614 dnl   glibc 2.3.6                          .  #  .  .  .  .  .  .  .  .
615 dnl   FreeBSD 5.4, 6.1                     .  ?  .  .  .  .  .  .  .  .
616 dnl   MacOS X 10.3.9                       .  #  .  .  .  .  .  .  .  .
617 dnl   OpenBSD 3.9, 4.0                     .  #  ?  .  .  .  .  .  ?  ?
618 dnl   Cygwin 2007                          .  #  #  .  .  .  .  .  .  ?
619 dnl   Cygwin 2006                          #  #  #  .  .  .  .  .  .  ?
620 dnl   Solaris 10                           .  #  .  .  .  .  .  .  .  .
621 dnl   Solaris 2.6 ... 9                    #  #  #  .  .  .  .  .  .  .
622 dnl   Solaris 2.5.1                        #  #  #  .  .  #  #  #  #  #
623 dnl   AIX 5.2                              .  #  .  .  .  .  .  .  .  .
624 dnl   AIX 4.3.2, 5.1                       #  #  #  .  .  .  .  .  .  .
625 dnl   HP-UX 11.31                          .  #  .  .  .  .  .  #  #  .
626 dnl   HP-UX 10.20, 11.00, 11.11, 11.23     #  #  #  .  .  .  .  #  #  #
627 dnl   IRIX 6.5                             #  #  #  .  .  .  .  #  .  .
628 dnl   OSF/1 5.1                            #  #  #  .  .  .  .  #  .  #
629 dnl   OSF/1 4.0d                           #  #  #  .  .  #  #  #  #  #
630 dnl   NetBSD 4.0                           .  ?  ?  .  .  .  .  .  ?  ?
631 dnl   NetBSD 3.0                           .  #  #  .  #  .  .  .  .  .
632 dnl   BeOS                                 #  #  #  .  #  .  .  .  .  .
633 dnl   mingw                                #  #  #  .  #  .  #  #  #  .