Skip to content

Commit

Permalink
gh-93202: Always use %zd printf formatter (#93201)
Browse files Browse the repository at this point in the history
Python now always use the ``%zu`` and ``%zd`` printf formats to
format a size_t or Py_ssize_t number. Building Python 3.12 requires a
C11 compiler, so these printf formats are now always supported.

* PyObject_Print() and _PyObject_Dump() now use the printf %zd format
  to display an object reference count.
* Update PY_FORMAT_SIZE_T comment.
* Remove outdated notes about the %zd format in PyBytes_FromFormat()
  and PyUnicode_FromFormat() documentations.
* configure no longer checks for the %zd format and no longer defines
  PY_FORMAT_SIZE_T macro in pyconfig.h.
* pymacconfig.h no longer undefines PY_FORMAT_SIZE_T: macOS 10.4 is
  no longer supported. Python 3.12 now requires macOS 10.6 (Snow
  Leopard) or newer.
  • Loading branch information
vstinner committed May 25, 2022
1 parent 9485a0d commit 71d8775
Show file tree
Hide file tree
Showing 10 changed files with 11 additions and 168 deletions.
3 changes: 0 additions & 3 deletions Doc/c-api/bytes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ called with a non-bytes parameter.
.. % XXX: This should be exactly the same as the table in PyErr_Format.
.. % One should just refer to the other.
.. % XXX: The descriptions for %zd and %zu are wrong, but the truth is complicated
.. % because not all compilers support the %z width modifier -- we fake it
.. % when necessary via interpolating PY_FORMAT_SIZE_T.
.. tabularcolumns:: |l|l|L|
Expand Down
4 changes: 0 additions & 4 deletions Doc/c-api/unicode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -397,10 +397,6 @@ APIs:
ASCII-encoded string. The following format characters are allowed:
.. % This should be exactly the same as the table in PyErr_Format.
.. % The descriptions for %zd and %zu are wrong, but the truth is complicated
.. % because not all compilers support the %z width modifier -- we fake it
.. % when necessary via interpolating PY_FORMAT_SIZE_T.
.. % Similar comments apply to the %ll width modifier and
.. tabularcolumns:: |l|l|L|
Expand Down
12 changes: 0 additions & 12 deletions Include/pymacconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,6 @@
# define HAVE_GCC_ASM_FOR_X87
#endif

/*
* The definition in pyconfig.h is only valid on the OS release
* where configure ran on and not necessarily for all systems where
* the executable can be used on.
*
* Specifically: OSX 10.4 has limited supported for '%zd', while
* 10.5 has full support for '%zd'. A binary built on 10.5 won't
* work properly on 10.4 unless we suppress the definition
* of PY_FORMAT_SIZE_T
*/
#undef PY_FORMAT_SIZE_T


#endif /* defined(_APPLE__) */

Expand Down
28 changes: 3 additions & 25 deletions Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,32 +186,10 @@ typedef Py_ssize_t Py_ssize_clean_t;
/* Largest possible value of size_t. */
#define PY_SIZE_MAX SIZE_MAX

/* Macro kept for backward compatibility: use "z" in new code.
/* Macro kept for backward compatibility: use directly "z" in new code.
*
* PY_FORMAT_SIZE_T is a platform-specific modifier for use in a printf
* format to convert an argument with the width of a size_t or Py_ssize_t.
* C99 introduced "z" for this purpose, but old MSVCs had not supported it.
* Since MSVC supports "z" since (at least) 2015, we can just use "z"
* for new code.
*
* These "high level" Python format functions interpret "z" correctly on
* all platforms (Python interprets the format string itself, and does whatever
* the platform C requires to convert a size_t/Py_ssize_t argument):
*
* PyBytes_FromFormat
* PyErr_Format
* PyBytes_FromFormatV
* PyUnicode_FromFormatV
*
* Lower-level uses require that you interpolate the correct format modifier
* yourself (e.g., calling printf, fprintf, sprintf, PyOS_snprintf); for
* example,
*
* Py_ssize_t index;
* fprintf(stderr, "index %" PY_FORMAT_SIZE_T "d sucks\n", index);
*
* That will expand to %zd or to something else correct for a Py_ssize_t on
* the platform.
* PY_FORMAT_SIZE_T is a modifier for use in a printf format to convert an
* argument with the width of a size_t or Py_ssize_t: "z" (C99).
*/
#ifndef PY_FORMAT_SIZE_T
# define PY_FORMAT_SIZE_T "z"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Python now always use the ``%zu`` and ``%zd`` printf formats to format a
``size_t`` or ``Py_ssize_t`` number. Building Python 3.12 requires a C11
compiler, so these printf formats are now always supported. Patch by Victor
Stinner.
4 changes: 2 additions & 2 deletions Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,9 @@ _ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape,
strcat(new_prefix, "(");
for (k = 0; k < ndim; ++k) {
if (k < ndim-1) {
sprintf(buf, "%"PY_FORMAT_SIZE_T"d,", shape[k]);
sprintf(buf, "%zd,", shape[k]);
} else {
sprintf(buf, "%"PY_FORMAT_SIZE_T"d)", shape[k]);
sprintf(buf, "%zd)", shape[k]);
}
strcat(new_prefix, buf);
}
Expand Down
9 changes: 2 additions & 7 deletions Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,8 @@ PyObject_Print(PyObject *op, FILE *fp, int flags)
}
else {
if (Py_REFCNT(op) <= 0) {
/* XXX(twouters) cast refcount to long until %zd is
universally available */
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "<refcnt %ld at %p>",
(long)Py_REFCNT(op), (void *)op);
fprintf(fp, "<refcnt %zd at %p>", Py_REFCNT(op), (void *)op);
Py_END_ALLOW_THREADS
}
else {
Expand Down Expand Up @@ -371,9 +368,7 @@ _PyObject_Dump(PyObject* op)

/* first, write fields which are the least likely to crash */
fprintf(stderr, "object address : %p\n", (void *)op);
/* XXX(twouters) cast refcount to long until %zd is
universally available */
fprintf(stderr, "object refcount : %ld\n", (long)Py_REFCNT(op));
fprintf(stderr, "object refcount : %zd\n", Py_REFCNT(op));
fflush(stderr);

PyTypeObject *type = Py_TYPE(op);
Expand Down
66 changes: 0 additions & 66 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 0 additions & 46 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -6004,52 +6004,6 @@ then
LIBS="$LIBS -framework CoreFoundation"
fi

AC_CACHE_CHECK([for %zd printf() format support], ac_cv_have_size_t_format, [dnl
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SSIZE_T
typedef ssize_t Py_ssize_t;
#elif SIZEOF_VOID_P == SIZEOF_LONG
typedef long Py_ssize_t;
#else
typedef int Py_ssize_t;
#endif
int main()
{
char buffer[256];
if(sprintf(buffer, "%zd", (size_t)123) < 0)
return 1;
if (strcmp(buffer, "123"))
return 1;
if (sprintf(buffer, "%zd", (Py_ssize_t)-123) < 0)
return 1;
if (strcmp(buffer, "-123"))
return 1;
return 0;
}
]])],
[ac_cv_have_size_t_format=yes],
[ac_cv_have_size_t_format=no],
[ac_cv_have_size_t_format="cross -- assuming yes"
])])
if test "$ac_cv_have_size_t_format" != no ; then
AC_DEFINE(PY_FORMAT_SIZE_T, "z",
[Define to printf format modifier for Py_ssize_t])
fi

AC_CHECK_TYPE(socklen_t,,
AC_DEFINE(socklen_t,int,
[Define to `int' if <sys/socket.h> does not define.]),[
Expand Down
3 changes: 0 additions & 3 deletions pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -1506,9 +1506,6 @@
/* Define if you want to coerce the C locale to a UTF-8 based locale */
#undef PY_COERCE_C_LOCALE

/* Define to printf format modifier for Py_ssize_t */
#undef PY_FORMAT_SIZE_T

/* Define to 1 to build the sqlite module with loadable extensions support. */
#undef PY_SQLITE_ENABLE_LOAD_EXTENSION

Expand Down

0 comments on commit 71d8775

Please sign in to comment.