summaryrefslogtreecommitdiff
path: root/config/c-library.m4
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-01-23 17:18:23 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2014-01-23 17:18:33 -0500
commitac4ef637ad2ff2a24847f67d14027b8745f6741e (patch)
treecb49061503740d1bd9a0c916df55a29b4973fa64 /config/c-library.m4
parentec8f692c3cd5760435712b7ec4afa8f014ed7b2e (diff)
downloadpostgresql-ac4ef637ad2ff2a24847f67d14027b8745f6741e.tar.gz
Allow use of "z" flag in our printf calls, and use it where appropriate.
Since C99, it's been standard for printf and friends to accept a "z" size modifier, meaning "whatever size size_t has". Up to now we've generally dealt with printing size_t values by explicitly casting them to unsigned long and using the "l" modifier; but this is really the wrong thing on platforms where pointers are wider than longs (such as Win64). So let's start using "z" instead. To ensure we can do that on all platforms, teach src/port/snprintf.c to understand "z", and add a configure test to force use of that implementation when the platform's version doesn't handle "z". Having done that, modify a bunch of places that were using the unsigned-long hack to use "z" instead. This patch doesn't pretend to have gotten everyplace that could benefit, but it catches many of them. I made an effort in particular to ensure that all uses of the same error message text were updated together, so as not to increase the number of translatable strings. It's possible that this change will result in format-string warnings from pre-C99 compilers. We might have to reconsider if there are any popular compilers that will warn about this; but let's start by seeing what the buildfarm thinks. Andres Freund, with a little additional work by me
Diffstat (limited to 'config/c-library.m4')
-rw-r--r--config/c-library.m458
1 files changed, 47 insertions, 11 deletions
diff --git a/config/c-library.m4 b/config/c-library.m4
index 1e3997bb1c..8f45010593 100644
--- a/config/c-library.m4
+++ b/config/c-library.m4
@@ -273,16 +273,16 @@ case $pgac_cv_snprintf_long_long_int_format in
esac])# PGAC_FUNC_SNPRINTF_LONG_LONG_INT_FORMAT
-# PGAC_FUNC_PRINTF_ARG_CONTROL
+# PGAC_FUNC_SNPRINTF_ARG_CONTROL
# ---------------------------------------
-# Determine if printf supports %1$ argument selection, e.g. %5$ selects
-# the fifth argument after the printf print string.
+# Determine if snprintf supports %1$ argument selection, e.g. %5$ selects
+# the fifth argument after the printf format string.
# This is not in the C99 standard, but in the Single Unix Specification (SUS).
# It is used in our language translation strings.
#
-AC_DEFUN([PGAC_FUNC_PRINTF_ARG_CONTROL],
-[AC_MSG_CHECKING([whether printf supports argument control])
-AC_CACHE_VAL(pgac_cv_printf_arg_control,
+AC_DEFUN([PGAC_FUNC_SNPRINTF_ARG_CONTROL],
+[AC_MSG_CHECKING([whether snprintf supports argument control])
+AC_CACHE_VAL(pgac_cv_snprintf_arg_control,
[AC_TRY_RUN([#include <stdio.h>
#include <string.h>
@@ -296,12 +296,48 @@ int main()
return 1;
return 0;
}],
-[pgac_cv_printf_arg_control=yes],
-[pgac_cv_printf_arg_control=no],
-[pgac_cv_printf_arg_control=cross])
+[pgac_cv_snprintf_arg_control=yes],
+[pgac_cv_snprintf_arg_control=no],
+[pgac_cv_snprintf_arg_control=cross])
])dnl AC_CACHE_VAL
-AC_MSG_RESULT([$pgac_cv_printf_arg_control])
-])# PGAC_FUNC_PRINTF_ARG_CONTROL
+AC_MSG_RESULT([$pgac_cv_snprintf_arg_control])
+])# PGAC_FUNC_SNPRINTF_ARG_CONTROL
+
+# PGAC_FUNC_SNPRINTF_SIZE_T_SUPPORT
+# ---------------------------------------
+# Determine if snprintf supports the z length modifier for printing
+# size_t-sized variables. That's supported by C99 and POSIX but not
+# all platforms play ball, so we must test whether it's working.
+#
+AC_DEFUN([PGAC_FUNC_SNPRINTF_SIZE_T_SUPPORT],
+[AC_MSG_CHECKING([whether snprintf supports the %z modifier])
+AC_CACHE_VAL(pgac_cv_snprintf_size_t_support,
+[AC_TRY_RUN([#include <stdio.h>
+#include <string.h>
+
+int main()
+{
+ char bufz[100];
+ char buf64[100];
+
+ /*
+ * Print the largest unsigned number fitting in a size_t using both %zu
+ * and the previously-determined format for 64-bit integers. Note that
+ * we don't run this code unless we know snprintf handles 64-bit ints.
+ */
+ bufz[0] = '\0'; /* in case snprintf fails to emit anything */
+ snprintf(bufz, sizeof(bufz), "%zu", ~((size_t) 0));
+ snprintf(buf64, sizeof(buf64), UINT64_FORMAT, (PG_INT64_TYPE) ~((size_t) 0));
+ if (strcmp(bufz, buf64) != 0)
+ return 1;
+ return 0;
+}],
+[pgac_cv_snprintf_size_t_support=yes],
+[pgac_cv_snprintf_size_t_support=no],
+[pgac_cv_snprintf_size_t_support=cross])
+])dnl AC_CACHE_VAL
+AC_MSG_RESULT([$pgac_cv_snprintf_size_t_support])
+])# PGAC_FUNC_SNPRINTF_SIZE_T_SUPPORT
# PGAC_TYPE_LOCALE_T