summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/pyerrors.h17
-rw-r--r--Misc/NEWS.d/next/C API/2020-06-15-16-46-01.bpo-36020.djI6jw.rst2
-rw-r--r--Modules/_ctypes/callbacks.c2
-rw-r--r--Modules/socketmodule.c7
-rw-r--r--Parser/tokenizer.c2
-rw-r--r--Python/mysnprintf.c27
6 files changed, 26 insertions, 31 deletions
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index 399bb7c..979a26b 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -4,6 +4,8 @@
extern "C" {
#endif
+#include <stdarg.h> // va_list
+
/* Error handling definitions */
PyAPI_FUNC(void) PyErr_SetNone(PyObject *);
@@ -307,21 +309,6 @@ PyAPI_FUNC(int) PyUnicodeTranslateError_SetReason(
const char *reason /* UTF-8 encoded string */
);
-/* These APIs aren't really part of the error implementation, but
- often needed to format error messages; the native C lib APIs are
- not available on all platforms, which is why we provide emulations
- for those platforms in Python/mysnprintf.c,
- WARNING: The return value of snprintf varies across platforms; do
- not rely on any particular behavior; eventually the C99 defn may
- be reliable.
-*/
-#if defined(MS_WIN32) && !defined(HAVE_SNPRINTF)
-# define HAVE_SNPRINTF
-# define snprintf _snprintf
-# define vsnprintf _vsnprintf
-#endif
-
-#include <stdarg.h>
PyAPI_FUNC(int) PyOS_snprintf(char *str, size_t size, const char *format, ...)
Py_GCC_ATTRIBUTE((format(printf, 3, 4)));
PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
diff --git a/Misc/NEWS.d/next/C API/2020-06-15-16-46-01.bpo-36020.djI6jw.rst b/Misc/NEWS.d/next/C API/2020-06-15-16-46-01.bpo-36020.djI6jw.rst
new file mode 100644
index 0000000..1f91dce
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2020-06-15-16-46-01.bpo-36020.djI6jw.rst
@@ -0,0 +1,2 @@
+On Windows, ``#include "pyerrors.h"`` no longer defines ``snprintf`` and
+``vsnprintf`` macros.
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c
index 29e8fac..2abfa67 100644
--- a/Modules/_ctypes/callbacks.c
+++ b/Modules/_ctypes/callbacks.c
@@ -84,7 +84,7 @@ PrintError(const char *msg, ...)
va_list marker;
va_start(marker, msg);
- vsnprintf(buf, sizeof(buf), msg, marker);
+ PyOS_vsnprintf(buf, sizeof(buf), msg, marker);
va_end(marker);
if (f != NULL && f != Py_None)
PyFile_WriteString(buf, f);
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index f60a27e..db0eeaa 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -436,13 +436,12 @@ remove_unusable_flags(PyObject *m)
#endif
#ifdef MS_WIN32
-#undef EAFNOSUPPORT
-#define EAFNOSUPPORT WSAEAFNOSUPPORT
-#define snprintf _snprintf
+# undef EAFNOSUPPORT
+# define EAFNOSUPPORT WSAEAFNOSUPPORT
#endif
#ifndef SOCKETCLOSE
-#define SOCKETCLOSE close
+# define SOCKETCLOSE close
#endif
#if (defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H)) && !defined(__NetBSD__) && !defined(__DragonFly__)
diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c
index d461e4e..f3c1d9b 100644
--- a/Parser/tokenizer.c
+++ b/Parser/tokenizer.c
@@ -1133,7 +1133,7 @@ verify_identifier(struct tok_state *tok)
Py_DECREF(s);
// PyUnicode_FromFormatV() does not support %X
char hex[9];
- snprintf(hex, sizeof(hex), "%04X", ch);
+ (void)PyOS_snprintf(hex, sizeof(hex), "%04X", ch);
if (Py_UNICODE_ISPRINTABLE(ch)) {
syntaxerror(tok, "invalid character '%c' (U+%s)", ch, hex);
}
diff --git a/Python/mysnprintf.c b/Python/mysnprintf.c
index 945a81a..458ca14 100644
--- a/Python/mysnprintf.c
+++ b/Python/mysnprintf.c
@@ -1,6 +1,8 @@
#include "Python.h"
-/* snprintf() wrappers. If the platform has vsnprintf, we use it, else we
+/* snprintf() and vsnprintf() wrappers.
+
+ If the platform has vsnprintf, we use it, else we
emulate it in a half-hearted way. Even if the platform has it, we wrap
it because platforms differ in what vsnprintf does in case the buffer
is too small: C99 behavior is to return the number of characters that
@@ -52,16 +54,17 @@ PyOS_snprintf(char *str, size_t size, const char *format, ...)
int
PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
{
+ assert(str != NULL);
+ assert(size > 0);
+ assert(format != NULL);
+
int len; /* # bytes written, excluding \0 */
-#ifdef HAVE_SNPRINTF
-#define _PyOS_vsnprintf_EXTRA_SPACE 1
+#if defined(_MSC_VER) || defined(HAVE_SNPRINTF)
+# define _PyOS_vsnprintf_EXTRA_SPACE 1
#else
-#define _PyOS_vsnprintf_EXTRA_SPACE 512
+# define _PyOS_vsnprintf_EXTRA_SPACE 512
char *buffer;
#endif
- assert(str != NULL);
- assert(size > 0);
- assert(format != NULL);
/* We take a size_t as input but return an int. Sanity check
* our input so that it won't cause an overflow in the
* vsnprintf return value or the buffer malloc size. */
@@ -70,10 +73,12 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
goto Done;
}
-#ifdef HAVE_SNPRINTF
+#if defined(_MSC_VER)
+ len = _vsnprintf(str, size, format, va);
+#elif defined(HAVE_SNPRINTF)
len = vsnprintf(str, size, format, va);
#else
- /* Emulate it. */
+ /* Emulate vsnprintf(). */
buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
if (buffer == NULL) {
len = -666;
@@ -96,9 +101,11 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
}
PyMem_FREE(buffer);
#endif
+
Done:
- if (size > 0)
+ if (size > 0) {
str[size-1] = '\0';
+ }
return len;
#undef _PyOS_vsnprintf_EXTRA_SPACE
}