snapshot before regression test
This commit is contained in:
200
includes/sys.py
Normal file
200
includes/sys.py
Normal file
@@ -0,0 +1,200 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import platmacro
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
|
||||
# Windows 后端依赖
|
||||
import w32.win32base
|
||||
import w32.win32process
|
||||
|
||||
# POSIX 后端依赖
|
||||
import posix
|
||||
|
||||
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# C 标准库 IO 声明
|
||||
# =============================================================================
|
||||
|
||||
def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass
|
||||
|
||||
def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass
|
||||
|
||||
# C 标准库 exit(刷新缓冲区后终止进程,跨平台)
|
||||
def exit(status: INT) -> VOID | t.CExtern | t.CExport: pass
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 平台信息
|
||||
# =============================================================================
|
||||
|
||||
# 最大整数值(64 位平台 ssize_t 上限)
|
||||
maxsize: t.CDefine = 9223372036854775807
|
||||
|
||||
|
||||
def platform() -> str:
|
||||
"""返回平台标识字符串('win32' 或 'linux')"""
|
||||
if platmacro.IS_WINDOWS:
|
||||
return "win32"
|
||||
return "linux"
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 进程信息
|
||||
# =============================================================================
|
||||
|
||||
def get_pid() -> int:
|
||||
"""返回当前进程 ID"""
|
||||
if platmacro.IS_WINDOWS:
|
||||
return w32.win32process.GetCurrentProcessId()
|
||||
return posix.getpid()
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 命令行参数(argv)
|
||||
# =============================================================================
|
||||
|
||||
# 全局 argv 状态(首次访问时初始化)
|
||||
_argc: INT = 0
|
||||
# _argv 是指针数组(char**),必须用 str | t.CPtr 使索引按 sizeof(char*) 步长
|
||||
# str 本身是 char*,| t.CPtr 再加一层指针 = char**
|
||||
# bytes | t.CPtr 也是 char**,可以同样用
|
||||
_argv: str | t.CPtr
|
||||
|
||||
|
||||
def _init_argv():
|
||||
"""初始化全局 argv(首次访问时调用一次)"""
|
||||
global _argc, _argv
|
||||
if _argc != 0:
|
||||
return
|
||||
if platmacro.IS_WINDOWS:
|
||||
_init_argv_win32()
|
||||
else:
|
||||
_init_argv_posix()
|
||||
|
||||
|
||||
def _init_argv_win32():
|
||||
"""Windows:GetCommandLineA + 手动解析(处理空格/双引号/反斜杠)"""
|
||||
global _argc, _argv
|
||||
cmdline: CHARPTR = w32.win32base.GetCommandLineA()
|
||||
if cmdline == None:
|
||||
return
|
||||
cmdlen: t.CSizeT = string.strlen(cmdline)
|
||||
if cmdlen == 0:
|
||||
return
|
||||
|
||||
# 分配参数字符串缓冲区(最坏情况:整个命令行 + argc 个 \0)
|
||||
buf: bytes = _mbuddy.alloc(cmdlen + 1)
|
||||
if buf == None:
|
||||
return
|
||||
|
||||
# 分配指针数组(最坏情况:每个字符都是一个参数)
|
||||
max_args: t.CSizeT = cmdlen + 1
|
||||
argv_arr: str | t.CPtr = (str | t.CPtr)(_mbuddy.alloc(max_args * platmacro.SIZEOF_POINTER))
|
||||
if argv_arr == None:
|
||||
return
|
||||
|
||||
argc: INT = 0
|
||||
i: t.CSizeT = 0
|
||||
j: t.CSizeT = 0
|
||||
in_quote: bool = False
|
||||
in_arg: bool = False
|
||||
|
||||
while i < cmdlen:
|
||||
ch: t.CInt = cmdline[i]
|
||||
if ch == 34: # 双引号
|
||||
in_quote = not in_quote
|
||||
if not in_arg:
|
||||
argv_arr[argc] = str(buf + j)
|
||||
argc += 1
|
||||
in_arg = True
|
||||
elif (ch == 32 or ch == 9) and not in_quote:
|
||||
# 空格或 Tab(引号外):参数分隔符
|
||||
if in_arg:
|
||||
buf[j] = 0
|
||||
j += 1
|
||||
in_arg = False
|
||||
else:
|
||||
if not in_arg:
|
||||
argv_arr[argc] = str(buf + j)
|
||||
argc += 1
|
||||
in_arg = True
|
||||
buf[j] = ch
|
||||
j += 1
|
||||
i += 1
|
||||
|
||||
if in_arg:
|
||||
buf[j] = 0
|
||||
|
||||
_argc = argc
|
||||
_argv = argv_arr
|
||||
|
||||
|
||||
def _init_argv_posix():
|
||||
"""POSIX:读取 /proc/self/cmdline(参数以 \\0 分隔,末尾双 \\0)"""
|
||||
global _argc, _argv
|
||||
fd: INT = posix.open("/proc/self/cmdline", posix.O_RDONLY, 0)
|
||||
if fd < 0:
|
||||
return
|
||||
|
||||
# 读取 cmdline(4KB 足够大多数情况)
|
||||
buf: bytes = _mbuddy.alloc(4096)
|
||||
if buf == None:
|
||||
posix.close(fd)
|
||||
return
|
||||
|
||||
total: ssize_t = posix.read(fd, buf, 4096)
|
||||
posix.close(fd)
|
||||
if total <= 0:
|
||||
return
|
||||
|
||||
# 计算参数个数(\0 分隔)
|
||||
argc: INT = 0
|
||||
i: t.CSizeT = 0
|
||||
total_size: t.CSizeT = t.CSizeT(total)
|
||||
while i < total_size:
|
||||
if buf[i] == 0:
|
||||
argc += 1
|
||||
i += 1
|
||||
|
||||
if argc == 0:
|
||||
return
|
||||
|
||||
# 分配指针数组
|
||||
argv_arr: str | t.CPtr = (str | t.CPtr)(_mbuddy.alloc(argc * platmacro.SIZEOF_POINTER))
|
||||
if argv_arr == None:
|
||||
return
|
||||
|
||||
# 填充指针(每个参数的起始地址)
|
||||
argv_arr[0] = str(buf)
|
||||
idx: INT = 1
|
||||
i = 0
|
||||
while i < total_size and idx < argc:
|
||||
if buf[i] == 0:
|
||||
argv_arr[idx] = str(buf + i + 1)
|
||||
idx += 1
|
||||
i += 1
|
||||
|
||||
_argc = argc
|
||||
_argv = argv_arr
|
||||
|
||||
|
||||
def argc() -> int:
|
||||
"""返回命令行参数个数。首次调用时自动初始化。"""
|
||||
if _argc == 0:
|
||||
_init_argv()
|
||||
return _argc
|
||||
|
||||
|
||||
def argv(index: int) -> str:
|
||||
"""返回第 index 个命令行参数(index 从 0 开始)。
|
||||
首次调用时自动初始化。索引越界返回 None。"""
|
||||
if _argc == 0:
|
||||
_init_argv()
|
||||
if index < 0 or index >= _argc:
|
||||
return None
|
||||
return _argv[index]
|
||||
Reference in New Issue
Block a user