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 and the _Interlocked* + * compiler intrinsics (both introduced in Visual Studio 2005, _MSC_VER + * 1400) as well as . 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 . */ +# include +#elif defined(_MSC_VER) #include #if defined(_M_IX86) || defined(_M_X64) # include @@ -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 /_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< 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__ "" +#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, "", 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, "", 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, "", &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, "", &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;