port: advance MSVC600 CPython compatibility frontier

This commit is contained in:
RayPals
2026-08-22 17:36:38 +00:00
parent a7a9560e5c
commit 824b4f0d24
15 changed files with 6150 additions and 41 deletions
+19 -8
View File
@@ -7,15 +7,16 @@
* three distinct patterns:
*
* 1. `status = _PyStatus_OK();` -- a compound-literal macro used as a
* plain assignment's right-hand side. Fixed by calling the existing
* public API function PyStatus_Ok() instead, which
* Python/initconfig.c defines as `return _PyStatus_OK();` -- the
* identical value, no header change needed.
* 2. `cf = _PyCompilerFlags_INIT;` -- likewise a compound-literal macro
* plain assignment's right-hand side. The shared macro now expands to
* a VC6-only internal helper that assigns PyStatus fields explicitly,
* while newer compilers keep the original compound-literal form.
* 2. `status = _PyStatus_ERR("...");` -- same compound-literal macro
* pattern for ERROR statuses, now using a VC6-only explicit helper.
* 3. `cf = _PyCompilerFlags_INIT;` -- likewise a compound-literal macro
* used as a plain assignment. Fixed by assigning PyCompilerFlags's
* two fields explicitly (cf_flags, cf_feature_version), matching the
* macro's own definition field-for-field.
* 3. `_PyArgv args = { .argc = argc, ... };` -- a designated-initializer
* 4. `_PyArgv args = { .argc = argc, ... };` -- a designated-initializer
* aggregate initializer with no macro involved. Fixed by declaring
* the variable bare and assigning each field explicitly; field order
* does not matter for plain assignment, unlike an initializer list.
@@ -35,8 +36,18 @@ vc6_status_ok_smoke(void)
{
PyStatus status;
/* pattern 1: was `status = _PyStatus_OK();` */
status = PyStatus_Ok();
/* pattern 1: VC6-only _PyStatus_OK() macro fallback helper. */
status = _PyStatus_OK();
return status;
}
PyStatus
vc6_status_error_smoke(void)
{
PyStatus status;
/* pattern 2: VC6-only _PyStatus_ERR() macro fallback helper. */
status = _PyStatus_ERR("vc6 status error smoke");
return status;
}
+59
View File
@@ -0,0 +1,59 @@
/* Focused compile smoke test for compat/msvc600/pathcch.h.
*
* The VC6 compatibility header intentionally implements only the single
* PathCch API used by cpython/Modules/getpath.c: PathCchFindExtension().
* This fixture keeps the representative path cases in one place for the
* VC6 probe. The probe is compile-only, so the checks are ordinary C code
* that can also be run later by a tiny Windows harness if needed.
*/
#include <windows.h>
#include <pathcch.h>
#ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
#endif
static int
pathcch_expect_ext(PCWSTR path, size_t cch, size_t offset)
{
PCWSTR ext;
HRESULT hr;
ext = NULL;
hr = PathCchFindExtension(path, cch, &ext);
return SUCCEEDED(hr) && ext == path + offset;
}
static int
pathcch_expect_invalid(PCWSTR path, size_t cch)
{
PCWSTR ext;
HRESULT hr;
ext = (PCWSTR)1;
hr = PathCchFindExtension(path, cch, &ext);
return FAILED(hr);
}
int
vc6_pathcch_find_extension_smoke(void)
{
static const WCHAR exe_path[] = L"C:\\Python311\\python.exe";
static const WCHAR no_ext[] = L"C:\\Python311\\python";
static const WCHAR dir_dot[] = L"C:\\tmp.dir\\python";
static const WCHAR dotfile[] = L"C:\\Python311\\.pythonrc";
static const WCHAR trailing_dir[] = L"C:\\bin\\python.exe\\";
static const WCHAR multi_dot[] = L"C:\\tmp\\archive.tar.gz";
int ok;
ok = 1;
ok = ok && pathcch_expect_ext(exe_path, ARRAYSIZE(exe_path), 20); /* .exe */
ok = ok && pathcch_expect_ext(no_ext, ARRAYSIZE(no_ext), 19); /* NUL */
ok = ok && pathcch_expect_ext(dir_dot, ARRAYSIZE(dir_dot), 17); /* NUL, directory dot ignored */
ok = ok && pathcch_expect_ext(dotfile, ARRAYSIZE(dotfile), 13); /* dotfile extension */
ok = ok && pathcch_expect_ext(trailing_dir, ARRAYSIZE(trailing_dir), 18); /* NUL after separator */
ok = ok && pathcch_expect_ext(multi_dot, ARRAYSIZE(multi_dot), 18); /* last suffix */
ok = ok && pathcch_expect_invalid(exe_path, 4); /* too small: no NUL */
ok = ok && pathcch_expect_invalid(NULL, ARRAYSIZE(exe_path));
return ok ? 0 : 1;
}
+76
View File
@@ -0,0 +1,76 @@
/* Focused compile smoke test for compat/msvc600/stdint.h.
*
* The VC6 compatibility header forwards to the existing
* compat/msvc600/inttypes.h typedefs. This fixture exercises exactly the
* subset that cpython/Modules/_blake2/impl/blake2-impl.h needs: uint8_t,
* uint32_t, and uint64_t, in the same load/store/rotate shapes that file
* uses, plus a compile-time width check for each. It also includes
* <inttypes.h> alongside <stdint.h> in the same translation unit, the way
* a Python.h + blake2.h translation unit would, to guard against the
* duplicate-typedef failure mode the stdint.h header is designed to avoid.
*/
#include <stddef.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
typedef char vc6_stdint_check_uint8_is_1_byte[(sizeof(uint8_t) == 1) ? 1 : -1];
typedef char vc6_stdint_check_uint32_is_4_bytes[(sizeof(uint32_t) == 4) ? 1 : -1];
typedef char vc6_stdint_check_uint64_is_8_bytes[(sizeof(uint64_t) == 8) ? 1 : -1];
static uint32_t
vc6_stdint_load32(const void *src)
{
const uint8_t *p = (const uint8_t *)src;
uint32_t w = *p++;
w |= ((uint32_t)(*p++)) << 8;
w |= ((uint32_t)(*p++)) << 16;
w |= ((uint32_t)(*p++)) << 24;
return w;
}
static uint64_t
vc6_stdint_load64(const void *src)
{
const uint8_t *p = (const uint8_t *)src;
uint64_t w = *p++;
w |= ((uint64_t)(*p++)) << 8;
w |= ((uint64_t)(*p++)) << 16;
w |= ((uint64_t)(*p++)) << 24;
w |= ((uint64_t)(*p++)) << 32;
w |= ((uint64_t)(*p++)) << 40;
w |= ((uint64_t)(*p++)) << 48;
w |= ((uint64_t)(*p++)) << 56;
return w;
}
static uint32_t
vc6_stdint_rotl32(const uint32_t w, const unsigned c)
{
return (w << c) | (w >> (32 - c));
}
static uint64_t
vc6_stdint_rotl64(const uint64_t w, const unsigned c)
{
return (w << c) | (w >> (64 - c));
}
int
vc6_stdint_smoke(void)
{
static const uint8_t bytes32[4] = { 0x01, 0x02, 0x03, 0x04 };
static const uint8_t bytes64[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
uint32_t w32;
uint64_t w64;
int ok;
w32 = vc6_stdint_load32(bytes32);
w64 = vc6_stdint_load64(bytes64);
ok = 1;
ok = ok && (w32 == 0x04030201UL);
ok = ok && (vc6_stdint_rotl32(w32, 8) == ((w32 << 8) | (w32 >> 24)));
ok = ok && (vc6_stdint_rotl64(w64, 8) == ((w64 << 8) | (w64 >> 56)));
return ok ? 0 : 1;
}