按规范「注释只讲解作用,不掺杂历史原因,尽量英文」:把 includes 下 75 个 .vp 的中文 # 注释与三引号 docstring 改写为英文,每个注释块压到 2 行以内。 保留要点:作用、约束、危险警告(不得/必须/注意)、ABI 与类型约定(如 BYTEPTR | t.CPtr = i8** 的跨模块坍缩坑)、位宽/长度约定、fail-fast 要求、内存与句柄所有权。 未动:文件头注释(规范豁免,仍是中文)、运行时中文字符串常量(printf / fatal_error / MlirFail 等用户可见消息,属代码字面量)。 验证:独立脚本比对 HEAD 与工作区的代码骨架(剥离 # 注释与三引号 docstring 后的非空行)——75 个文件逐字节一致;行尾 CRLF/LF 未被改动;全文剩余中文仅 547 行头注释、0 条行尾注释。bootstrap 三重重编 SUCCESS;全量 77/77 顺序回归通过。
243 lines
7.9 KiB
Plaintext
243 lines
7.9 KiB
Plaintext
import t, c
|
|
from stdint import *
|
|
import w32.win32base
|
|
import w32.win32file
|
|
import memhub
|
|
import stdlib
|
|
|
|
|
|
# Maximum Windows path length
|
|
define MAX_PATH_LEN = 260
|
|
|
|
# INVALID_FILE_ATTRIBUTES
|
|
define INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF
|
|
|
|
# Module-level global MBuddy pointer (initialized by the user in main)
|
|
_mbuddy: memhub.MemBuddy*
|
|
|
|
|
|
# =============================================================================
|
|
# File/Directory Attribute Query
|
|
# =============================================================================
|
|
|
|
def _get_attrs(path: str) -> ULONG:
|
|
"""Get file attributes. Return INVALID_FILE_ATTRIBUTES on failure."""
|
|
return w32.win32file.GetFileAttributesA(path)
|
|
|
|
|
|
def exists(path: str) -> bool:
|
|
"""Check whether the file/directory exists"""
|
|
attrs: ULONG = _get_attrs(path)
|
|
if attrs == INVALID_FILE_ATTRIBUTES:
|
|
return False
|
|
return True
|
|
|
|
|
|
def isdir(path: str) -> bool:
|
|
"""Check whether the path is a directory"""
|
|
attrs: ULONG = _get_attrs(path)
|
|
if attrs == INVALID_FILE_ATTRIBUTES:
|
|
return False
|
|
if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0:
|
|
return True
|
|
return False
|
|
|
|
|
|
def isfile(path: str) -> bool:
|
|
"""Check whether the path is a regular file"""
|
|
attrs: ULONG = _get_attrs(path)
|
|
if attrs == INVALID_FILE_ATTRIBUTES:
|
|
return False
|
|
if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0:
|
|
return False
|
|
return True
|
|
|
|
|
|
def getsize(path: str) -> int64:
|
|
"""Return the file size in bytes. Return -1 on failure."""
|
|
handle: w32.win32base.HANDLE = w32.win32file.CreateFileA(
|
|
path, w32.win32file.GENERIC_READ, w32.win32file.FILE_SHARE_READ,
|
|
t.CPtr(0), w32.win32file.OPEN_EXISTING, w32.win32file.FILE_ATTRIBUTE_NORMAL, t.CPtr(0)
|
|
)
|
|
if handle == w32.win32base.INVALID_HANDLE_VALUE:
|
|
return -1
|
|
li: w32.win32base.LARGE_INTEGER = w32.win32base.LARGE_INTEGER()
|
|
result: BOOL = w32.win32file.GetFileSizeEx(handle, t.CPtr(&li))
|
|
w32.win32base.CloseHandle(handle)
|
|
if result == 0:
|
|
return -1
|
|
return li.QuadPart
|
|
|
|
|
|
# =============================================================================
|
|
# Working Directory
|
|
# =============================================================================
|
|
|
|
def getcwd() -> str:
|
|
"""Return the current working directory (memory allocated via _mbuddy)"""
|
|
buf: bytes = _mbuddy.alloc(MAX_PATH_LEN + 1)
|
|
if buf == None: return None
|
|
length: ULONG = w32.win32file.GetCurrentDirectoryA(MAX_PATH_LEN + 1, buf)
|
|
if length == 0:
|
|
return None
|
|
if length > MAX_PATH_LEN:
|
|
# Buffer too small; reallocate
|
|
buf2: bytes = _mbuddy.alloc(length + 1)
|
|
if buf2 == None: return None
|
|
w32.win32file.GetCurrentDirectoryA(length + 1, buf2)
|
|
buf2[length] = 0
|
|
return str(buf2)
|
|
buf[length] = 0
|
|
return str(buf)
|
|
|
|
|
|
def chdir(path: str) -> int:
|
|
"""Switch the current working directory. Return 0 on success, -1 on failure."""
|
|
result: BOOL = w32.win32file.SetCurrentDirectoryA(path)
|
|
if result == 0:
|
|
return -1
|
|
return 0
|
|
|
|
|
|
# =============================================================================
|
|
# File/Directory Operations
|
|
# =============================================================================
|
|
|
|
def mkdir(path: str) -> int:
|
|
"""Create a directory. Return 0 on success, -1 on failure.
|
|
If path is valid UTF-8, convert to UTF-16 and use CreateDirectoryW; otherwise fall back to the A-series."""
|
|
if w32.win32base.utf8_is_valid(path) == 0:
|
|
result: BOOL = w32.win32file.CreateDirectoryA(path, t.CPtr(0))
|
|
if result == 0:
|
|
return -1
|
|
return 0
|
|
wp: w32.win32base.WCHARPTR = w32.win32base.utf8_to_utf16_dup(path)
|
|
if wp is None:
|
|
result_a: BOOL = w32.win32file.CreateDirectoryA(path, t.CPtr(0))
|
|
if result_a == 0:
|
|
return -1
|
|
return 0
|
|
result_w: BOOL = w32.win32file.CreateDirectoryW(t.CPtr(wp), t.CPtr(0))
|
|
stdlib.free(wp)
|
|
if result_w == 0:
|
|
return -1
|
|
return 0
|
|
|
|
|
|
def remove(path: str) -> int:
|
|
"""Delete a file. Return 0 on success, -1 on failure."""
|
|
result: BOOL = w32.win32file.DeleteFileA(path)
|
|
if result == 0:
|
|
return -1
|
|
return 0
|
|
|
|
|
|
def rmdir(path: str) -> int:
|
|
"""Delete an empty directory. Return 0 on success, -1 on failure."""
|
|
result: BOOL = w32.win32file.RemoveDirectoryA(path)
|
|
if result == 0:
|
|
return -1
|
|
return 0
|
|
|
|
|
|
def rename(old_path: str, new_path: str) -> int:
|
|
"""Rename/move a file or directory. Return 0 on success, -1 on failure."""
|
|
result: BOOL = w32.win32file.MoveFileExA(
|
|
old_path, new_path,
|
|
w32.win32file.MOVEFILE_REPLACE_EXISTING | w32.win32file.MOVEFILE_COPY_ALLOWED
|
|
)
|
|
if result == 0:
|
|
return -1
|
|
return 0
|
|
|
|
|
|
def chmod(path: str, mode: int) -> int:
|
|
"""Modify file attributes (simplified Windows: read-only bit only).
|
|
S_IWUSR (0o200) in mode: 0 sets read-only, 1 sets writable. Return 0 on success, -1 on failure."""
|
|
if (mode & 0o200) != 0:
|
|
# Writable: clear the read-only attribute
|
|
result: BOOL = w32.win32file.SetFileAttributesA(
|
|
path, w32.win32file.FILE_ATTRIBUTE_NORMAL
|
|
)
|
|
else:
|
|
# Read-only: set the read-only attribute
|
|
result: BOOL = w32.win32file.SetFileAttributesA(
|
|
path, w32.win32file.FILE_ATTRIBUTE_READONLY
|
|
)
|
|
if result == 0:
|
|
return -1
|
|
return 0
|
|
|
|
|
|
# =============================================================================
|
|
# Directory Listing (FindFirstFile / FindNextFile)
|
|
# =============================================================================
|
|
|
|
def listdir(path: str, out_names: str*, max_count: ULONG) -> ULONG:
|
|
"""List file/subdirectory names under a directory.
|
|
out_names is a caller-provided char** array (each entry points to a filename allocated via _mbuddy); max_count is its capacity. Return the count, or 0 on failure."""
|
|
# Build search pattern: path\*
|
|
path_len: sizet = len(path)
|
|
pattern: bytes = _mbuddy.alloc(path_len + 3)
|
|
if pattern == None: return 0
|
|
i: sizet = 0
|
|
for ch in path:
|
|
pattern[i] = ch
|
|
i += 1
|
|
# Append \* suffix
|
|
if path[path_len - 1] != '\\' and path[path_len - 1] != '/':
|
|
pattern[i] = '\\'
|
|
i += 1
|
|
pattern[i] = '*'
|
|
i += 1
|
|
pattern[i] = 0
|
|
|
|
find_data: w32.win32file.WIN32_FIND_DATAA = w32.win32file.WIN32_FIND_DATAA()
|
|
handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, t.CPtr(&find_data))
|
|
if handle == w32.win32base.INVALID_HANDLE_VALUE:
|
|
return 0
|
|
|
|
count: ULONG = 0
|
|
while count < max_count:
|
|
# Skip . and ..
|
|
name: str = find_data.cFileName
|
|
if name[0] == '.':
|
|
if name[1] == 0:
|
|
# "."
|
|
if w32.win32file.FindNextFileA(handle, t.CPtr(&find_data)) == 0:
|
|
break
|
|
continue
|
|
if name[1] == '.' and name[2] == 0:
|
|
# ".."
|
|
if w32.win32file.FindNextFileA(handle, t.CPtr(&find_data)) == 0:
|
|
break
|
|
continue
|
|
|
|
# Copy the filename into newly allocated memory
|
|
name_len: sizet = len(name)
|
|
name_buf: bytes = _mbuddy.alloc(name_len + 1)
|
|
if name_buf == None: break
|
|
j: sizet = 0
|
|
for ch in name:
|
|
name_buf[j] = ch
|
|
j += 1
|
|
name_buf[name_len] = 0
|
|
out_names[count] = str(name_buf)
|
|
count += 1
|
|
|
|
if w32.win32file.FindNextFileA(handle, t.CPtr(&find_data)) == 0:
|
|
break
|
|
|
|
w32.win32file.FindClose(handle)
|
|
return count
|
|
|
|
|
|
# =============================================================================
|
|
# Command Execution
|
|
# =============================================================================
|
|
|
|
def system(cmd: str) -> int:
|
|
"""Execute a command line command (via the C runtime system()).
|
|
Output goes to the child terminal (inherits parent stdout/stderr). Return the exit code (0 = success)."""
|
|
return stdlib.system(cmd)
|