201 lines
5.4 KiB
Python
201 lines
5.4 KiB
Python
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]
|