port: add MSVC600 CPython compatibility layer
This commit is contained in:
@@ -1,8 +1,356 @@
|
||||
diff --git a/Include/internal/pycore_atomic.h b/Include/internal/pycore_atomic.h
|
||||
index 425d69f..748de28 100644
|
||||
--- a/Include/internal/pycore_atomic.h
|
||||
+++ b/Include/internal/pycore_atomic.h
|
||||
@@ -16,7 +16,21 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
-#if defined(_MSC_VER)
|
||||
+/* Visual C++ 6.0 (_MSC_VER 1200) predates <intrin.h> and the _Interlocked*
|
||||
+ * compiler intrinsics (both introduced in Visual Studio 2005, _MSC_VER
|
||||
+ * 1400) as well as <immintrin.h>. This port only targets 32-bit x86 under
|
||||
+ * VC6, so gate the modern-MSVC include on that combination and give VC6/x86
|
||||
+ * a project-local branch below (_Py_ATOMIC_VC6_X86) built on the Win32
|
||||
+ * Interlocked* API instead. Every other compiler/version keeps the
|
||||
+ * unmodified upstream behavior.
|
||||
+ */
|
||||
+#if defined(_MSC_VER) && _MSC_VER < 1300 && defined(_M_IX86)
|
||||
+# define _Py_ATOMIC_VC6_X86 1
|
||||
+ /* Declares InterlockedExchange()/InterlockedCompareExchange(), used by
|
||||
+ * the _Py_ATOMIC_VC6_X86 branch below in place of the _Interlocked*
|
||||
+ * intrinsics the modern-MSVC branch gets from <intrin.h>. */
|
||||
+# include <windows.h>
|
||||
+#elif defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#if defined(_M_IX86) || defined(_M_X64)
|
||||
# include <immintrin.h>
|
||||
@@ -238,7 +252,87 @@ _Py_ANNOTATE_MEMORY_ORDER(const volatile void *address, _Py_memory_order order)
|
||||
This might affect performance but likely only in some very specific and
|
||||
hard to measure scenario.
|
||||
*/
|
||||
-#if defined(_M_IX86) || defined(_M_X64)
|
||||
+#if defined(_Py_ATOMIC_VC6_X86)
|
||||
+/* VC6 / Windows 9x, 32-bit x86 only (_M_X64 is never defined by VC6).
|
||||
+ VC6 has neither <intrin.h>/_Interlocked* compiler intrinsics (Visual
|
||||
+ Studio 2005+) nor the _HLEAcquire/_HLERelease hardware-lock-elision
|
||||
+ variants (Visual Studio 2013+) used by the modern-MSVC branch below.
|
||||
+ Substitute the plain Win32 InterlockedExchange/InterlockedCompareExchange
|
||||
+ functions, which are exported by KERNEL32.DLL on Windows 98 (this VC6
|
||||
+ SDK's WINBASE.H declares them for _M_IX86 as compiler-intrinsic-backed
|
||||
+ APIs, not the newer MRx000/Alpha-only intrinsic path above them in that
|
||||
+ header). Like the modern-MSVC intrinsics, these give a full memory
|
||||
+ barrier, so -- as with the HLE fallback described above -- every
|
||||
+ _Py_memory_order maps to the same fully-fenced operation; there is no
|
||||
+ separate acquire/release-only path to take.
|
||||
+
|
||||
+ _Py_atomic_address (uintptr_t) and _Py_atomic_int (int) are both 4
|
||||
+ bytes on this 32-bit-only target, so the 64-bit store/load paths used
|
||||
+ by the modern-MSVC branch below (guarded there by `sizeof(...) == 8`)
|
||||
+ are unreachable here and are intentionally not implemented: this port
|
||||
+ has no Win9x-era substitute for CMPXCHG8B-based 64-bit atomics. Fail
|
||||
+ loudly at compile time rather than silently mishandling a 64-bit
|
||||
+ target if this header is ever pulled into a VC6 build configured for
|
||||
+ one (VC6 itself never defines _M_X64, so this should not trigger).
|
||||
+*/
|
||||
+#if defined(_M_X64)
|
||||
+#error "VC6 64-bit atomics are not implemented; this port only targets 32-bit x86 (_M_IX86)."
|
||||
+#endif
|
||||
+
|
||||
+typedef enum _Py_memory_order {
|
||||
+ _Py_memory_order_relaxed,
|
||||
+ _Py_memory_order_acquire,
|
||||
+ _Py_memory_order_release,
|
||||
+ _Py_memory_order_acq_rel,
|
||||
+ _Py_memory_order_seq_cst
|
||||
+} _Py_memory_order;
|
||||
+
|
||||
+typedef struct _Py_atomic_address {
|
||||
+ volatile uintptr_t _value;
|
||||
+} _Py_atomic_address;
|
||||
+
|
||||
+typedef struct _Py_atomic_int {
|
||||
+ volatile int _value;
|
||||
+} _Py_atomic_int;
|
||||
+
|
||||
+static __inline long
|
||||
+_Py_vc6_InterlockedExchange(volatile long *target, long value)
|
||||
+{
|
||||
+ return InterlockedExchange((LPLONG)target, value);
|
||||
+}
|
||||
+
|
||||
+static __inline long
|
||||
+_Py_vc6_InterlockedCompareExchange(volatile long *destination, long exchange, long comperand)
|
||||
+{
|
||||
+ return (long)InterlockedCompareExchange(
|
||||
+ (PVOID *)destination, (PVOID)exchange, (PVOID)comperand);
|
||||
+}
|
||||
+
|
||||
+#define _Py_atomic_store_32bit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
+ ((void)_Py_vc6_InterlockedExchange( \
|
||||
+ (volatile long *)&((ATOMIC_VAL)->_value), (long)(NEW_VAL)))
|
||||
+
|
||||
+static __inline int
|
||||
+_Py_atomic_load_32bit_impl(volatile int *value, int order)
|
||||
+{
|
||||
+ long old;
|
||||
+ (void)order;
|
||||
+ do {
|
||||
+ old = *(volatile long *)value;
|
||||
+ } while (_Py_vc6_InterlockedCompareExchange((volatile long *)value, old, old) != old);
|
||||
+ return (int)old;
|
||||
+}
|
||||
+
|
||||
+#define _Py_atomic_load_32bit(ATOMIC_VAL, ORDER) \
|
||||
+ _Py_atomic_load_32bit_impl((volatile int *)&((ATOMIC_VAL)->_value), (ORDER))
|
||||
+
|
||||
+#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
+ _Py_atomic_store_32bit((ATOMIC_VAL), (NEW_VAL), (ORDER))
|
||||
+
|
||||
+#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \
|
||||
+ _Py_atomic_load_32bit((ATOMIC_VAL), (ORDER))
|
||||
+
|
||||
+#elif defined(_M_IX86) || defined(_M_X64)
|
||||
typedef enum _Py_memory_order {
|
||||
_Py_memory_order_relaxed,
|
||||
_Py_memory_order_acquire,
|
||||
diff --git a/Include/internal/pycore_call.h b/Include/internal/pycore_call.h
|
||||
index 3ccacfa..3098e1e 100644
|
||||
--- a/Include/internal/pycore_call.h
|
||||
+++ b/Include/internal/pycore_call.h
|
||||
@@ -38,18 +38,21 @@ extern PyObject * _PyObject_CallMethodFormat(
|
||||
static inline vectorcallfunc
|
||||
_PyVectorcall_FunctionInline(PyObject *callable)
|
||||
{
|
||||
+ PyTypeObject *tp;
|
||||
+ Py_ssize_t offset;
|
||||
+ vectorcallfunc ptr;
|
||||
+
|
||||
assert(callable != NULL);
|
||||
|
||||
- PyTypeObject *tp = Py_TYPE(callable);
|
||||
+ tp = Py_TYPE(callable);
|
||||
if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL)) {
|
||||
return NULL;
|
||||
}
|
||||
assert(PyCallable_Check(callable));
|
||||
|
||||
- Py_ssize_t offset = tp->tp_vectorcall_offset;
|
||||
+ offset = tp->tp_vectorcall_offset;
|
||||
assert(offset > 0);
|
||||
|
||||
- vectorcallfunc ptr;
|
||||
memcpy(&ptr, (char *) callable + offset, sizeof(ptr));
|
||||
return ptr;
|
||||
}
|
||||
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
|
||||
index 3a24a65..4db8abc 100644
|
||||
--- a/Include/internal/pycore_code.h
|
||||
+++ b/Include/internal/pycore_code.h
|
||||
@@ -149,18 +149,20 @@ typedef unsigned char _PyLocals_Kind;
|
||||
static inline _PyLocals_Kind
|
||||
_PyLocals_GetKind(PyObject *kinds, int i)
|
||||
{
|
||||
+ char *ptr;
|
||||
assert(PyBytes_Check(kinds));
|
||||
assert(0 <= i && i < PyBytes_GET_SIZE(kinds));
|
||||
- char *ptr = PyBytes_AS_STRING(kinds);
|
||||
+ ptr = PyBytes_AS_STRING(kinds);
|
||||
return (_PyLocals_Kind)(ptr[i]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_PyLocals_SetKind(PyObject *kinds, int i, _PyLocals_Kind kind)
|
||||
{
|
||||
+ char *ptr;
|
||||
assert(PyBytes_Check(kinds));
|
||||
assert(0 <= i && i < PyBytes_GET_SIZE(kinds));
|
||||
- char *ptr = PyBytes_AS_STRING(kinds);
|
||||
+ ptr = PyBytes_AS_STRING(kinds);
|
||||
ptr[i] = (char) kind;
|
||||
}
|
||||
|
||||
@@ -520,11 +522,12 @@ adaptive_counter_start(void) {
|
||||
static inline uint16_t
|
||||
adaptive_counter_backoff(uint16_t counter) {
|
||||
unsigned int backoff = counter & ((1<<ADAPTIVE_BACKOFF_BITS)-1);
|
||||
+ unsigned int value;
|
||||
backoff++;
|
||||
if (backoff > MAX_BACKOFF_VALUE) {
|
||||
backoff = MAX_BACKOFF_VALUE;
|
||||
}
|
||||
- unsigned int value = (1 << backoff) - 1;
|
||||
+ value = (1 << backoff) - 1;
|
||||
return adaptive_counter_bits(value, backoff);
|
||||
}
|
||||
|
||||
diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h
|
||||
index dc308fe..16feaf3 100644
|
||||
--- a/Include/internal/pycore_dict.h
|
||||
+++ b/Include/internal/pycore_dict.h
|
||||
@@ -163,9 +163,11 @@ extern PyObject *_PyDict_FromItems(
|
||||
static inline void
|
||||
_PyDictValues_AddToInsertionOrder(PyDictValues *values, Py_ssize_t ix)
|
||||
{
|
||||
+ uint8_t *size_ptr;
|
||||
+ int size;
|
||||
assert(ix < SHARED_KEYS_MAX_SIZE);
|
||||
- uint8_t *size_ptr = ((uint8_t *)values)-2;
|
||||
- int size = *size_ptr;
|
||||
+ size_ptr = ((uint8_t *)values)-2;
|
||||
+ size = *size_ptr;
|
||||
assert(size+2 < ((uint8_t *)values)[-1]);
|
||||
size++;
|
||||
size_ptr[-size] = (uint8_t)ix;
|
||||
diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h
|
||||
index 860dce1..da38ee6 100644
|
||||
--- a/Include/internal/pycore_list.h
|
||||
+++ b/Include/internal/pycore_list.h
|
||||
@@ -43,10 +43,12 @@ _PyList_AppendTakeRefListResize(PyListObject *self, PyObject *newitem);
|
||||
static inline int
|
||||
_PyList_AppendTakeRef(PyListObject *self, PyObject *newitem)
|
||||
{
|
||||
+ Py_ssize_t len;
|
||||
+ Py_ssize_t allocated;
|
||||
assert(self != NULL && newitem != NULL);
|
||||
assert(PyList_Check(self));
|
||||
- Py_ssize_t len = PyList_GET_SIZE(self);
|
||||
- Py_ssize_t allocated = self->allocated;
|
||||
+ len = PyList_GET_SIZE(self);
|
||||
+ allocated = self->allocated;
|
||||
assert((size_t)len + 1 < PY_SSIZE_T_MAX);
|
||||
if (allocated > len) {
|
||||
PyList_SET_ITEM(self, len, newitem);
|
||||
diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
|
||||
index f022f82..d1c55ae 100644
|
||||
--- a/Include/internal/pycore_object.h
|
||||
+++ b/Include/internal/pycore_object.h
|
||||
@@ -14,6 +14,14 @@ extern "C" {
|
||||
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
||||
#include "pycore_runtime.h" // _PyRuntime
|
||||
|
||||
+/* Visual C++ 6.0 predates C99's __func__ predefined identifier. It also
|
||||
+ lacks MSVC's later __FUNCTION__ extension, so provide a VC6-only fallback
|
||||
+ for debug/fatal diagnostics in this header without changing any other
|
||||
+ compiler's function-name reporting. */
|
||||
+#if defined(_MSC_VER) && _MSC_VER < 1300 && !defined(__func__)
|
||||
+# define __func__ "<unknown>"
|
||||
+#endif
|
||||
+
|
||||
#define _PyObject_IMMORTAL_INIT(type) \
|
||||
{ \
|
||||
.ob_refcnt = 999999999, \
|
||||
@@ -125,19 +133,24 @@ static inline void _PyObject_GC_TRACK(
|
||||
#endif
|
||||
PyObject *op)
|
||||
{
|
||||
+ PyGC_Head *gc;
|
||||
+ PyInterpreterState *interp;
|
||||
+ PyGC_Head *generation0;
|
||||
+ PyGC_Head *last;
|
||||
+
|
||||
_PyObject_ASSERT_FROM(op, !_PyObject_GC_IS_TRACKED(op),
|
||||
"object already tracked by the garbage collector",
|
||||
filename, lineno, __func__);
|
||||
|
||||
- PyGC_Head *gc = _Py_AS_GC(op);
|
||||
+ gc = _Py_AS_GC(op);
|
||||
_PyObject_ASSERT_FROM(op,
|
||||
(gc->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0,
|
||||
"object is in generation which is garbage collected",
|
||||
filename, lineno, __func__);
|
||||
|
||||
- PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
- PyGC_Head *generation0 = interp->gc.generation0;
|
||||
- PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev);
|
||||
+ interp = _PyInterpreterState_GET();
|
||||
+ generation0 = interp->gc.generation0;
|
||||
+ last = (PyGC_Head*)(generation0->_gc_prev);
|
||||
_PyGCHead_SET_NEXT(last, gc);
|
||||
_PyGCHead_SET_PREV(gc, last);
|
||||
_PyGCHead_SET_NEXT(gc, generation0);
|
||||
@@ -161,13 +174,17 @@ static inline void _PyObject_GC_UNTRACK(
|
||||
#endif
|
||||
PyObject *op)
|
||||
{
|
||||
+ PyGC_Head *gc;
|
||||
+ PyGC_Head *prev;
|
||||
+ PyGC_Head *next;
|
||||
+
|
||||
_PyObject_ASSERT_FROM(op, _PyObject_GC_IS_TRACKED(op),
|
||||
"object not tracked by the garbage collector",
|
||||
filename, lineno, __func__);
|
||||
|
||||
- PyGC_Head *gc = _Py_AS_GC(op);
|
||||
- PyGC_Head *prev = _PyGCHead_PREV(gc);
|
||||
- PyGC_Head *next = _PyGCHead_NEXT(gc);
|
||||
+ gc = _Py_AS_GC(op);
|
||||
+ prev = _PyGCHead_PREV(gc);
|
||||
+ next = _PyGCHead_NEXT(gc);
|
||||
_PyGCHead_SET_NEXT(prev, next);
|
||||
_PyGCHead_SET_PREV(next, prev);
|
||||
gc->_gc_next = 0;
|
||||
diff --git a/Include/longobject.h b/Include/longobject.h
|
||||
index 778cb62..d25edf7 100644
|
||||
--- a/Include/longobject.h
|
||||
+++ b/Include/longobject.h
|
||||
@@ -81,12 +81,12 @@ PyAPI_FUNC(double) PyLong_AsDouble(PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyLong_FromVoidPtr(void *);
|
||||
PyAPI_FUNC(void *) PyLong_AsVoidPtr(PyObject *);
|
||||
|
||||
-PyAPI_FUNC(PyObject *) PyLong_FromLongLong(long long);
|
||||
-PyAPI_FUNC(PyObject *) PyLong_FromUnsignedLongLong(unsigned long long);
|
||||
-PyAPI_FUNC(long long) PyLong_AsLongLong(PyObject *);
|
||||
-PyAPI_FUNC(unsigned long long) PyLong_AsUnsignedLongLong(PyObject *);
|
||||
-PyAPI_FUNC(unsigned long long) PyLong_AsUnsignedLongLongMask(PyObject *);
|
||||
-PyAPI_FUNC(long long) PyLong_AsLongLongAndOverflow(PyObject *, int *);
|
||||
+PyAPI_FUNC(PyObject *) PyLong_FromLongLong(PY_LONG_LONG);
|
||||
+PyAPI_FUNC(PyObject *) PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG);
|
||||
+PyAPI_FUNC(PY_LONG_LONG) PyLong_AsLongLong(PyObject *);
|
||||
+PyAPI_FUNC(unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(PyObject *);
|
||||
+PyAPI_FUNC(unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLongMask(PyObject *);
|
||||
+PyAPI_FUNC(PY_LONG_LONG) PyLong_AsLongLongAndOverflow(PyObject *, int *);
|
||||
|
||||
PyAPI_FUNC(PyObject *) PyLong_FromString(const char *, char **, int);
|
||||
|
||||
diff --git a/Include/pyexpat.h b/Include/pyexpat.h
|
||||
index a676e16..017e86d 100644
|
||||
--- a/Include/pyexpat.h
|
||||
+++ b/Include/pyexpat.h
|
||||
@@ -54,12 +54,12 @@ struct PyExpat_CAPI
|
||||
XML_Bool (*SetReparseDeferralEnabled)(XML_Parser parser, XML_Bool enabled);
|
||||
/* might be NULL for expat < 2.7.2 */
|
||||
XML_Bool (*SetAllocTrackerActivationThreshold)(
|
||||
- XML_Parser parser, unsigned long long activationThresholdBytes);
|
||||
+ XML_Parser parser, unsigned PY_LONG_LONG activationThresholdBytes);
|
||||
XML_Bool (*SetAllocTrackerMaximumAmplification)(
|
||||
XML_Parser parser, float maxAmplificationFactor);
|
||||
/* might be NULL for expat < 2.4.0 */
|
||||
XML_Bool (*SetBillionLaughsAttackProtectionActivationThreshold)(
|
||||
- XML_Parser parser, unsigned long long activationThresholdBytes);
|
||||
+ XML_Parser parser, unsigned PY_LONG_LONG activationThresholdBytes);
|
||||
XML_Bool (*SetBillionLaughsAttackProtectionMaximumAmplification)(
|
||||
XML_Parser parser, float maxAmplificationFactor);
|
||||
/* might be NULL for expat < 2.8.0 */
|
||||
diff --git a/Include/pyport.h b/Include/pyport.h
|
||||
index b3b8b6f..4da45ef 100644
|
||||
index b3b8b6f..ae930fc 100644
|
||||
--- a/Include/pyport.h
|
||||
+++ b/Include/pyport.h
|
||||
@@ -334,9 +334,12 @@ extern "C" {
|
||||
@@ -97,6 +97,13 @@ Used in: Py_SAFE_DOWNCAST
|
||||
#define PY_ULLONG_MAX ULLONG_MAX
|
||||
#endif
|
||||
|
||||
+/* Spelling of 64 bit integer literal suffixes; see PC/pyconfig.h for the
|
||||
+ compilers that need something other than the C99 LL/ULL suffixes. */
|
||||
+#ifndef PY_LL
|
||||
+#define PY_LL(x) x##LL
|
||||
+#define PY_ULL(x) x##ULL
|
||||
+#endif
|
||||
+
|
||||
#define PY_UINT32_T uint32_t
|
||||
#define PY_UINT64_T uint64_t
|
||||
|
||||
@@ -334,9 +341,12 @@ extern "C" {
|
||||
#if defined(__GNUC__) \
|
||||
&& ((__GNUC__ >= 4) || (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))
|
||||
#define Py_DEPRECATED(VERSION_UNUSED) __attribute__((__deprecated__))
|
||||
@@ -16,7 +364,7 @@ index b3b8b6f..4da45ef 100644
|
||||
#else
|
||||
#define Py_DEPRECATED(VERSION_UNUSED)
|
||||
#endif
|
||||
@@ -352,10 +355,14 @@ extern "C" {
|
||||
@@ -352,10 +362,14 @@ extern "C" {
|
||||
#define _Py_COMP_DIAG_IGNORE_DEPR_DECLS \
|
||||
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
|
||||
#define _Py_COMP_DIAG_POP _Pragma("GCC diagnostic pop")
|
||||
@@ -32,3 +380,388 @@ index b3b8b6f..4da45ef 100644
|
||||
#else
|
||||
#define _Py_COMP_DIAG_PUSH
|
||||
#define _Py_COMP_DIAG_IGNORE_DEPR_DECLS
|
||||
diff --git a/Include/pythread.h b/Include/pythread.h
|
||||
index a483290..defdaf1 100644
|
||||
--- a/Include/pythread.h
|
||||
+++ b/Include/pythread.h
|
||||
@@ -40,23 +40,23 @@ PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int);
|
||||
module exposes a higher-level API, with timeouts expressed in seconds
|
||||
and floating-point numbers allowed.
|
||||
*/
|
||||
-#define PY_TIMEOUT_T long long
|
||||
+#define PY_TIMEOUT_T PY_LONG_LONG
|
||||
|
||||
#if defined(_POSIX_THREADS)
|
||||
/* PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000),
|
||||
convert microseconds to nanoseconds. */
|
||||
-# define PY_TIMEOUT_MAX (LLONG_MAX / 1000)
|
||||
+# define PY_TIMEOUT_MAX (PY_LLONG_MAX / 1000)
|
||||
#elif defined (NT_THREADS)
|
||||
// WaitForSingleObject() accepts timeout in milliseconds in the range
|
||||
// [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no
|
||||
// timeout. 0xFFFFFFFE milliseconds is around 49.7 days.
|
||||
-# if 0xFFFFFFFELL * 1000 < LLONG_MAX
|
||||
-# define PY_TIMEOUT_MAX (0xFFFFFFFELL * 1000)
|
||||
+# if PY_LL(0xFFFFFFFE) * 1000 < PY_LLONG_MAX
|
||||
+# define PY_TIMEOUT_MAX (PY_LL(0xFFFFFFFE) * 1000)
|
||||
# else
|
||||
-# define PY_TIMEOUT_MAX LLONG_MAX
|
||||
+# define PY_TIMEOUT_MAX PY_LLONG_MAX
|
||||
# endif
|
||||
#else
|
||||
-# define PY_TIMEOUT_MAX LLONG_MAX
|
||||
+# define PY_TIMEOUT_MAX PY_LLONG_MAX
|
||||
#endif
|
||||
|
||||
|
||||
diff --git a/Modules/main.c b/Modules/main.c
|
||||
index f6dade1..011ae59 100644
|
||||
--- a/Modules/main.c
|
||||
+++ b/Modules/main.c
|
||||
@@ -35,13 +35,14 @@ static PyStatus
|
||||
pymain_init(const _PyArgv *args)
|
||||
{
|
||||
PyStatus status;
|
||||
+ PyPreConfig preconfig;
|
||||
+ PyConfig config;
|
||||
|
||||
status = _PyRuntime_Initialize();
|
||||
if (_PyStatus_EXCEPTION(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
- PyPreConfig preconfig;
|
||||
PyPreConfig_InitPythonConfig(&preconfig);
|
||||
|
||||
status = _Py_PreInitializeFromPyArgv(&preconfig, args);
|
||||
@@ -49,7 +50,6 @@ pymain_init(const _PyArgv *args)
|
||||
return status;
|
||||
}
|
||||
|
||||
- PyConfig config;
|
||||
PyConfig_InitPythonConfig(&config);
|
||||
|
||||
/* pass NULL as the config: config is read from command line arguments,
|
||||
@@ -68,7 +68,13 @@ pymain_init(const _PyArgv *args)
|
||||
if (_PyStatus_EXCEPTION(status)) {
|
||||
goto done;
|
||||
}
|
||||
- status = _PyStatus_OK();
|
||||
+ /* VC6 (MSVC600) has no C99 compound literals, so _PyStatus_OK() (a
|
||||
+ compound literal macro) cannot be used here; PyStatus_Ok() is the
|
||||
+ public API function that returns the identical value
|
||||
+ (Python/initconfig.c: `PyStatus PyStatus_Ok(void) { return
|
||||
+ _PyStatus_OK(); }`), so this is not a behavior change for any
|
||||
+ compiler. */
|
||||
+ status = PyStatus_Ok();
|
||||
|
||||
done:
|
||||
PyConfig_Clear(&config);
|
||||
@@ -202,6 +208,8 @@ pymain_header(const PyConfig *config)
|
||||
static void
|
||||
pymain_import_readline(const PyConfig *config)
|
||||
{
|
||||
+ PyObject *mod;
|
||||
+
|
||||
if (config->isolated) {
|
||||
return;
|
||||
}
|
||||
@@ -212,7 +220,7 @@ pymain_import_readline(const PyConfig *config)
|
||||
return;
|
||||
}
|
||||
|
||||
- PyObject *mod = PyImport_ImportModule("readline");
|
||||
+ mod = PyImport_ImportModule("readline");
|
||||
if (mod == NULL) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
@@ -234,6 +242,7 @@ pymain_run_command(wchar_t *command)
|
||||
{
|
||||
PyObject *unicode, *bytes;
|
||||
int ret;
|
||||
+ PyCompilerFlags cf;
|
||||
|
||||
unicode = PyUnicode_FromWideChar(command, -1);
|
||||
if (unicode == NULL) {
|
||||
@@ -250,7 +259,12 @@ pymain_run_command(wchar_t *command)
|
||||
goto error;
|
||||
}
|
||||
|
||||
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
|
||||
+ /* VC6 has no C99 compound literals/designated initializers, so
|
||||
+ _PyCompilerFlags_INIT (`(PyCompilerFlags){.cf_flags = 0,
|
||||
+ .cf_feature_version = PY_MINOR_VERSION}`) cannot be used as an
|
||||
+ initializer here; assign the same two fields explicitly instead. */
|
||||
+ cf.cf_flags = 0;
|
||||
+ cf.cf_feature_version = PY_MINOR_VERSION;
|
||||
cf.cf_flags |= PyCF_IGNORE_COOKIE;
|
||||
ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), &cf);
|
||||
Py_DECREF(bytes);
|
||||
@@ -317,11 +331,16 @@ static int
|
||||
pymain_run_file_obj(PyObject *program_name, PyObject *filename,
|
||||
int skip_source_first_line)
|
||||
{
|
||||
+ FILE *fp;
|
||||
+ struct _Py_stat_struct sb;
|
||||
+ PyCompilerFlags cf;
|
||||
+ int run;
|
||||
+
|
||||
if (PySys_Audit("cpython.run_file", "O", filename) < 0) {
|
||||
return pymain_exit_err_print();
|
||||
}
|
||||
|
||||
- FILE *fp = _Py_fopen_obj(filename, "rb");
|
||||
+ fp = _Py_fopen_obj(filename, "rb");
|
||||
if (fp == NULL) {
|
||||
// Ignore the OSError
|
||||
PyErr_Clear();
|
||||
@@ -341,7 +360,6 @@ pymain_run_file_obj(PyObject *program_name, PyObject *filename,
|
||||
}
|
||||
}
|
||||
|
||||
- struct _Py_stat_struct sb;
|
||||
if (_Py_fstat_noraise(fileno(fp), &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
PySys_FormatStderr("%S: %R is a directory, cannot continue\n",
|
||||
program_name, filename);
|
||||
@@ -356,28 +374,35 @@ pymain_run_file_obj(PyObject *program_name, PyObject *filename,
|
||||
}
|
||||
|
||||
/* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */
|
||||
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
|
||||
- int run = _PyRun_AnyFileObject(fp, filename, 1, &cf);
|
||||
+ /* See pymain_run_command() above for why this is not
|
||||
+ _PyCompilerFlags_INIT (VC6 has no compound literals). */
|
||||
+ cf.cf_flags = 0;
|
||||
+ cf.cf_feature_version = PY_MINOR_VERSION;
|
||||
+ run = _PyRun_AnyFileObject(fp, filename, 1, &cf);
|
||||
return (run != 0);
|
||||
}
|
||||
|
||||
static int
|
||||
pymain_run_file(const PyConfig *config)
|
||||
{
|
||||
- PyObject *filename = PyUnicode_FromWideChar(config->run_filename, -1);
|
||||
+ PyObject *filename;
|
||||
+ PyObject *program_name;
|
||||
+ int res;
|
||||
+
|
||||
+ filename = PyUnicode_FromWideChar(config->run_filename, -1);
|
||||
if (filename == NULL) {
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
- PyObject *program_name = PyUnicode_FromWideChar(config->program_name, -1);
|
||||
+ program_name = PyUnicode_FromWideChar(config->program_name, -1);
|
||||
if (program_name == NULL) {
|
||||
Py_DECREF(filename);
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
- int res = pymain_run_file_obj(program_name, filename,
|
||||
- config->skip_source_first_line);
|
||||
+ res = pymain_run_file_obj(program_name, filename,
|
||||
+ config->skip_source_first_line);
|
||||
Py_DECREF(filename);
|
||||
Py_DECREF(program_name);
|
||||
return res;
|
||||
@@ -388,12 +413,20 @@ static int
|
||||
pymain_run_startup(PyConfig *config, int *exitcode)
|
||||
{
|
||||
int ret;
|
||||
+ PyObject *startup = NULL;
|
||||
+#ifdef MS_WINDOWS
|
||||
+ const wchar_t *env;
|
||||
+#else
|
||||
+ const char *env;
|
||||
+#endif
|
||||
+ FILE *fp;
|
||||
+ PyCompilerFlags cf;
|
||||
+
|
||||
if (!config->use_environment) {
|
||||
return 0;
|
||||
}
|
||||
- PyObject *startup = NULL;
|
||||
#ifdef MS_WINDOWS
|
||||
- const wchar_t *env = _wgetenv(L"PYTHONSTARTUP");
|
||||
+ env = _wgetenv(L"PYTHONSTARTUP");
|
||||
if (env == NULL || env[0] == L'\0') {
|
||||
return 0;
|
||||
}
|
||||
@@ -402,7 +435,7 @@ pymain_run_startup(PyConfig *config, int *exitcode)
|
||||
goto error;
|
||||
}
|
||||
#else
|
||||
- const char *env = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP");
|
||||
+ env = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP");
|
||||
if (env == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -415,7 +448,7 @@ pymain_run_startup(PyConfig *config, int *exitcode)
|
||||
goto error;
|
||||
}
|
||||
|
||||
- FILE *fp = _Py_fopen_obj(startup, "r");
|
||||
+ fp = _Py_fopen_obj(startup, "r");
|
||||
if (fp == NULL) {
|
||||
int save_errno = errno;
|
||||
PyErr_Clear();
|
||||
@@ -426,7 +459,10 @@ pymain_run_startup(PyConfig *config, int *exitcode)
|
||||
goto error;
|
||||
}
|
||||
|
||||
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
|
||||
+ /* See pymain_run_command() above for why this is not
|
||||
+ _PyCompilerFlags_INIT (VC6 has no compound literals). */
|
||||
+ cf.cf_flags = 0;
|
||||
+ cf.cf_feature_version = PY_MINOR_VERSION;
|
||||
(void) _PyRun_SimpleFileObject(fp, startup, 0, &cf);
|
||||
PyErr_Clear();
|
||||
fclose(fp);
|
||||
@@ -482,11 +518,15 @@ pymain_run_interactive_hook(int *exitcode)
|
||||
static int
|
||||
pymain_run_stdin(PyConfig *config)
|
||||
{
|
||||
+ PyCompilerFlags cf;
|
||||
+ int run;
|
||||
+
|
||||
if (stdin_is_interactive(config)) {
|
||||
+ int exitcode;
|
||||
+
|
||||
config->inspect = 0;
|
||||
Py_InspectFlag = 0; /* do exit on SystemExit */
|
||||
|
||||
- int exitcode;
|
||||
if (pymain_run_startup(config, &exitcode)) {
|
||||
return exitcode;
|
||||
}
|
||||
@@ -505,8 +545,11 @@ pymain_run_stdin(PyConfig *config)
|
||||
return pymain_exit_err_print();
|
||||
}
|
||||
|
||||
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
|
||||
- int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf);
|
||||
+ /* See pymain_run_command() above for why this is not
|
||||
+ _PyCompilerFlags_INIT (VC6 has no compound literals). */
|
||||
+ cf.cf_flags = 0;
|
||||
+ cf.cf_feature_version = PY_MINOR_VERSION;
|
||||
+ run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf);
|
||||
return (run != 0);
|
||||
}
|
||||
|
||||
@@ -514,6 +557,9 @@ pymain_run_stdin(PyConfig *config)
|
||||
static void
|
||||
pymain_repl(PyConfig *config, int *exitcode)
|
||||
{
|
||||
+ PyCompilerFlags cf;
|
||||
+ int res;
|
||||
+
|
||||
/* Check this environment variable at the end, to give programs the
|
||||
opportunity to set it from Python. */
|
||||
if (!config->inspect && _Py_GetEnv(config->use_environment, "PYTHONINSPECT")) {
|
||||
@@ -535,8 +581,11 @@ pymain_repl(PyConfig *config, int *exitcode)
|
||||
return;
|
||||
}
|
||||
|
||||
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
|
||||
- int res = PyRun_AnyFileFlags(stdin, "<stdin>", &cf);
|
||||
+ /* See pymain_run_command() above for why this is not
|
||||
+ _PyCompilerFlags_INIT (VC6 has no compound literals). */
|
||||
+ cf.cf_flags = 0;
|
||||
+ cf.cf_feature_version = PY_MINOR_VERSION;
|
||||
+ res = PyRun_AnyFileFlags(stdin, "<stdin>", &cf);
|
||||
*exitcode = (res != 0);
|
||||
}
|
||||
|
||||
@@ -718,11 +767,15 @@ pymain_main(_PyArgv *args)
|
||||
int
|
||||
Py_Main(int argc, wchar_t **argv)
|
||||
{
|
||||
- _PyArgv args = {
|
||||
- .argc = argc,
|
||||
- .use_bytes_argv = 0,
|
||||
- .bytes_argv = NULL,
|
||||
- .wchar_argv = argv};
|
||||
+ /* VC6 has no C99 designated initializers, so the aggregate initializer
|
||||
+ below cannot be used; assign each field explicitly instead (field
|
||||
+ order does not matter for plain assignment, unlike the initializer
|
||||
+ list it replaces). */
|
||||
+ _PyArgv args;
|
||||
+ args.argc = argc;
|
||||
+ args.use_bytes_argv = 0;
|
||||
+ args.bytes_argv = NULL;
|
||||
+ args.wchar_argv = argv;
|
||||
return pymain_main(&args);
|
||||
}
|
||||
|
||||
@@ -730,11 +783,12 @@ Py_Main(int argc, wchar_t **argv)
|
||||
int
|
||||
Py_BytesMain(int argc, char **argv)
|
||||
{
|
||||
- _PyArgv args = {
|
||||
- .argc = argc,
|
||||
- .use_bytes_argv = 1,
|
||||
- .bytes_argv = argv,
|
||||
- .wchar_argv = NULL};
|
||||
+ /* See Py_Main() above: VC6 has no C99 designated initializers. */
|
||||
+ _PyArgv args;
|
||||
+ args.argc = argc;
|
||||
+ args.use_bytes_argv = 1;
|
||||
+ args.bytes_argv = argv;
|
||||
+ args.wchar_argv = NULL;
|
||||
return pymain_main(&args);
|
||||
}
|
||||
|
||||
diff --git a/PC/pyconfig.h b/PC/pyconfig.h
|
||||
index 959b851..6d8ce84 100644
|
||||
--- a/PC/pyconfig.h
|
||||
+++ b/PC/pyconfig.h
|
||||
@@ -256,6 +256,19 @@ typedef int pid_t;
|
||||
# define PY_ULLONG_MAX _UI64_MAX
|
||||
#endif
|
||||
|
||||
+/* Spelling of 64 bit integer literal suffixes. MSVC before Visual C++ .NET
|
||||
+ (_MSC_VER < 1300, i.e. Visual C++ 6.0 and earlier) rejects the C99 LL/ULL
|
||||
+ suffixes and spells them i64/ui64 instead. */
|
||||
+#ifndef PY_LL
|
||||
+# if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
+# define PY_LL(x) x##i64
|
||||
+# define PY_ULL(x) x##ui64
|
||||
+# else
|
||||
+# define PY_LL(x) x##LL
|
||||
+# define PY_ULL(x) x##ULL
|
||||
+# endif
|
||||
+#endif
|
||||
+
|
||||
/* For Windows the Python core is in a DLL by default. Test
|
||||
Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */
|
||||
#if !defined(MS_NO_COREDLL) && !defined(Py_NO_ENABLE_SHARED)
|
||||
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
|
||||
index 9248e97..a2220e9 100644
|
||||
--- a/Python/pylifecycle.c
|
||||
+++ b/Python/pylifecycle.c
|
||||
@@ -88,8 +88,14 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS
|
||||
|
||||
#if defined(MS_WINDOWS)
|
||||
|
||||
+# if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
+/* VC6 does not support #pragma section plus __declspec(allocate()).
|
||||
+ Use its older data_seg spelling for this initialized object instead. */
|
||||
+# pragma data_seg("PyRuntime")
|
||||
+# else
|
||||
#pragma section("PyRuntime", read, write)
|
||||
__declspec(allocate("PyRuntime"))
|
||||
+# endif
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
@@ -104,6 +110,9 @@ _PyRuntimeState _PyRuntime
|
||||
__attribute__ ((section (".PyRuntime")))
|
||||
#endif
|
||||
= _PyRuntimeState_INIT;
|
||||
+#if defined(MS_WINDOWS) && defined(_MSC_VER) && _MSC_VER < 1300
|
||||
+# pragma data_seg()
|
||||
+#endif
|
||||
_Py_COMP_DIAG_POP
|
||||
|
||||
static int runtime_initialized = 0;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef PYTHON_WIN9X_MSVC600_STDBOOL_H
|
||||
#define PYTHON_WIN9X_MSVC600_STDBOOL_H
|
||||
|
||||
/* VC6-only fallback for the C99 <stdbool.h> header.
|
||||
*
|
||||
* Visual C++ 6.0 (_MSC_VER 1200) predates C99 and ships no <stdbool.h>;
|
||||
* in VC6's C mode `bool`/`true`/`false` are not keywords at all (they are
|
||||
* C++-only there). This project-local header is found ahead of any system
|
||||
* <stdbool.h> only because compat/msvc600 is placed first on the VC6 probe
|
||||
* scripts' include path (scripts/vc6-probe.sh, scripts/vc6-probe-core.sh);
|
||||
* it is never installed anywhere a standards-conforming compiler's own
|
||||
* <stdbool.h> would be found instead, so it never shadows a real one. The
|
||||
* _MSC_VER guard below is defence in depth for that same reason, and keeps
|
||||
* this file inert (and diagnosable, via the #error) if it is ever reached
|
||||
* by a compiler other than the VC6 this port targets.
|
||||
*
|
||||
* Modeled on the standard C99 <stdbool.h> contract: defines the macros
|
||||
* bool, true, false, and __bool_true_false_are_defined, and (matching
|
||||
* C99, which requires a program be able to #undef/redefine bool/true/
|
||||
* false) leaves them as plain macros rather than a typedef, so existing
|
||||
* C99-style `#undef bool` idioms, were CPython to use one, would still
|
||||
* work.
|
||||
*/
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1300
|
||||
#error "compat/msvc600/stdbool.h is a VC6-only (_MSC_VER < 1300) fallback; a standard <stdbool.h> should be used instead."
|
||||
#endif
|
||||
|
||||
#define bool int
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#endif /* PYTHON_WIN9X_MSVC600_STDBOOL_H */
|
||||
Reference in New Issue
Block a user