768 lines
27 KiB
Diff
768 lines
27 KiB
Diff
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..ae930fc 100644
|
|
--- a/Include/pyport.h
|
|
+++ b/Include/pyport.h
|
|
@@ -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__))
|
|
-#elif defined(_MSC_VER)
|
|
+#elif defined(_MSC_VER) && _MSC_VER >= 1300
|
|
#define Py_DEPRECATED(VERSION) __declspec(deprecated( \
|
|
"deprecated in " #VERSION))
|
|
+#elif defined(_MSC_VER)
|
|
+/* Visual C++ 6.0 has no supported deprecation declaration syntax. */
|
|
+#define Py_DEPRECATED(VERSION_UNUSED)
|
|
#else
|
|
#define Py_DEPRECATED(VERSION_UNUSED)
|
|
#endif
|
|
@@ -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")
|
|
-#elif defined(_MSC_VER)
|
|
+#elif defined(_MSC_VER) && _MSC_VER >= 1300
|
|
#define _Py_COMP_DIAG_PUSH __pragma(warning(push))
|
|
#define _Py_COMP_DIAG_IGNORE_DEPR_DECLS __pragma(warning(disable: 4996))
|
|
#define _Py_COMP_DIAG_POP __pragma(warning(pop))
|
|
+#elif defined(_MSC_VER)
|
|
+#define _Py_COMP_DIAG_PUSH
|
|
+#define _Py_COMP_DIAG_IGNORE_DEPR_DECLS
|
|
+#define _Py_COMP_DIAG_POP
|
|
#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;
|