summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/pyerrors.h16
-rw-r--r--Makefile.pre.in1
-rw-r--r--Python/modsupport.c16
-rw-r--r--Python/mysnprintf.c96
4 files changed, 124 insertions, 5 deletions
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index 3c57e2f..bfc36ae 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -106,6 +106,22 @@ extern DL_IMPORT(void) PyErr_SetInterrupt(void);
extern DL_IMPORT(void) PyErr_SyntaxLocation(char *, int);
extern DL_IMPORT(PyObject *) PyErr_ProgramText(char *, int);
+/* 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 */
+#if defined(MS_WIN32) && !defined(HAVE_SNPRINTF)
+# define HAVE_SNPRINTF
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+#endif
+#ifndef HAVE_SNPRINTF
+extern DL_IMPORT(int) PyOS_snprintf(char *str, size_t size, const char *format, ...);
+extern DL_IMPORT(int) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va);
+#else
+# define PyOS_vsnprintf vsnprintf
+# define PyOS_snprintf snprintf
+#endif
#ifdef __cplusplus
}
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 3ca3397..9fbf29d 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -214,6 +214,7 @@ PYTHON_OBJS= \
Python/marshal.o \
Python/modsupport.o \
Python/mystrtoul.o \
+ Python/mysnprintf.o \
Python/pyfpe.o \
Python/pystate.o \
Python/pythonrun.o \
diff --git a/Python/modsupport.c b/Python/modsupport.c
index 0868589..eb0818c 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -26,8 +26,8 @@ char *_Py_PackageContext = NULL;
*/
static char api_version_warning[] =
-"WARNING: Python C API version mismatch for module %s:\n\
- This Python has API version %d, module %s has version %d.\n";
+"Python C API version mismatch for module %.100s:\
+ This Python has API version %d, module %.100s has version %d.";
PyObject *
Py_InitModule4(char *name, PyMethodDef *methods, char *doc,
@@ -37,9 +37,15 @@ Py_InitModule4(char *name, PyMethodDef *methods, char *doc,
PyMethodDef *ml;
if (!Py_IsInitialized())
Py_FatalError("Interpreter not initialized (version mismatch?)");
- if (module_api_version != PYTHON_API_VERSION)
- fprintf(stderr, api_version_warning,
- name, PYTHON_API_VERSION, name, module_api_version);
+ if (module_api_version != PYTHON_API_VERSION) {
+ char message[512];
+ PyOS_snprintf(message, sizeof(message),
+ api_version_warning, name,
+ PYTHON_API_VERSION, name,
+ module_api_version);
+ if (PyErr_Warn(PyExc_RuntimeWarning, message))
+ return NULL;
+ }
if (_Py_PackageContext != NULL) {
char *p = strrchr(_Py_PackageContext, '.');
if (p != NULL && strcmp(name, p+1) == 0) {
diff --git a/Python/mysnprintf.c b/Python/mysnprintf.c
new file mode 100644
index 0000000..e6c3fce
--- /dev/null
+++ b/Python/mysnprintf.c
@@ -0,0 +1,96 @@
+
+#include "Python.h"
+
+/* snprintf() emulation for platforms which don't have it (yet).
+
+ Return value
+
+ The number of characters printed (not including the trailing
+ `\0' used to end output to strings) or a negative number in
+ case of an error.
+
+ PyOS_snprintf and PyOS_vsnprintf do not write more than size
+ bytes (including the trailing '\0').
+
+ If the output would have been truncated, they return the number
+ of characters (excluding the trailing '\0') which would have
+ been written to the final string if enough space had been
+ available. This is inline with the C99 standard.
+
+*/
+
+#include <ctype.h>
+
+#ifndef HAVE_SNPRINTF
+
+static
+int myvsnprintf(char *str, size_t size, const char *format, va_list va)
+{
+ char *buffer = PyMem_Malloc(size + 512);
+ int len;
+
+ if (buffer == NULL)
+ return -1;
+ len = vsprintf(buffer, format, va);
+ if (len < 0) {
+ PyMem_Free(buffer);
+ return len;
+ }
+ len++;
+ if (len > size + 512)
+ Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
+ if (len > size) {
+ PyMem_Free(buffer);
+ return len - 1;
+ }
+ memcpy(str, buffer, len);
+ PyMem_Free(buffer);
+ return len - 1;
+}
+
+int PyOS_snprintf(char *str, size_t size, const char *format, ...)
+{
+ int rc;
+ va_list va;
+
+ va_start(va, format);
+ rc = myvsnprintf(str, size, format, va);
+ va_end(va);
+ return rc;
+}
+
+int PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
+{
+ return myvsnprintf(str, size, format, va);
+}
+
+#else
+
+/* Make sure that a C API is included in the lib */
+
+#ifdef PyOS_snprintf
+# undef PyOS_snprintf
+#endif
+
+int PyOS_snprintf(char *str, size_t size, const char *format, ...)
+{
+ int rc;
+ va_list va;
+
+ va_start(va, format);
+ rc = vsnprintf(str, size, format, va);
+ va_end(va);
+ return rc;
+}
+
+#ifdef PyOS_vsnprintf
+# undef PyOS_vsnprintf
+#endif
+
+int PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
+{
+ return vsnprintf(str, size, format, va);
+}
+
+#endif
+