Rewrote the comments in the libraries under 'includes' in English (excluding those inside folders)
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import memhub
|
||||
import stdio
|
||||
@@ -7,9 +6,9 @@ import hashtable
|
||||
|
||||
|
||||
# ============================================================
|
||||
# argparse.py — 命令行参数解析库(Python argparse 风格)
|
||||
# argparse.vp — Command line argument parsing library, inspired by Python argparse
|
||||
#
|
||||
# 用法:
|
||||
# Usage:
|
||||
# argparse._mbuddy = mb
|
||||
# parser = argparse.ArgumentParser("myprog", "A test", pool=mb)
|
||||
# parser.add_argument("--input", "-i", arg_type=argparse.STRING,
|
||||
@@ -23,49 +22,49 @@ import hashtable
|
||||
# args = parser.parse_args(argc, argv)
|
||||
# if args is not None:
|
||||
# inp: str = args.get_str("input")
|
||||
# cnt: INT = args.get_int("count")
|
||||
# cnt: int = args.get_int("count")
|
||||
# verb: bool = args.get_bool("verbose")
|
||||
# out: str = args.get_str("output")
|
||||
# argparse.release(args)
|
||||
# ============================================================
|
||||
|
||||
# 类型常量
|
||||
# Type constants
|
||||
STRING: t.CDefine = 0
|
||||
INT: t.CDefine = 1
|
||||
BOOL: t.CDefine = 2
|
||||
|
||||
# 动作常量
|
||||
# Action constants
|
||||
STORE: t.CDefine = 0
|
||||
STORE_TRUE: t.CDefine = 1
|
||||
STORE_FALSE: t.CDefine = 2
|
||||
COUNT: t.CDefine = 3
|
||||
|
||||
# 限制
|
||||
# Limits
|
||||
MAX_ARGS: t.CDefine = 32
|
||||
|
||||
# 模块级 mbuddy 指针(由用户在 main 中赋值)
|
||||
# Module-level membuddy pointer (assigned inside main by user)
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Argument — 参数定义结构体
|
||||
# Argument — Argument definition structure
|
||||
# ============================================================
|
||||
|
||||
class Argument:
|
||||
name: str # "--input" 或 "output"(位置参数)
|
||||
short_name: str # "-i" 或 None
|
||||
help_text: str # 帮助文本
|
||||
arg_type: INT # STRING, INT, BOOL
|
||||
action: INT # STORE, STORE_TRUE, STORE_FALSE, COUNT
|
||||
default_int: INT # INT 类型默认值
|
||||
default_str: str # STRING 类型默认值
|
||||
required: bool # 是否必须
|
||||
is_positional: bool # 是否位置参数
|
||||
dest: str # 查找键名("--input" → "input")
|
||||
name: str # "--input" or positional "output"
|
||||
short_name: str # "-i" or null
|
||||
help_text: str # Help description text
|
||||
arg_type: int # STRING, INT, BOOL
|
||||
action: int # STORE, STORE_TRUE, STORE_FALSE, COUNT
|
||||
default_int: int # Default value for integer types
|
||||
default_str: str # Default value for string types
|
||||
required: bool # Whether this argument is mandatory
|
||||
is_positional: bool # True for positional parameters
|
||||
dest: str # Lookup key ("--input" → "input")
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ParsedArgs — 解析结果
|
||||
# ParsedArgs — Parsing result container
|
||||
# ============================================================
|
||||
|
||||
class ParsedArgs:
|
||||
@@ -80,30 +79,33 @@ class ParsedArgs:
|
||||
self._ht = hashtable.HashTable(mb)
|
||||
|
||||
def get_str(self, name: str) -> str:
|
||||
"""获取字符串值。键不存在返回 None。"""
|
||||
if self._ht.__contains__(name) == 0: return None
|
||||
"""Fetch string value. Returns None if key not found."""
|
||||
if self._ht.__contains__(name) == 0:
|
||||
return None
|
||||
return self._ht[name]
|
||||
|
||||
def get_int(self, name: str) -> INT:
|
||||
"""获取整数值。键不存在返回 0。"""
|
||||
if self._ht.__contains__(name) == 0: return 0
|
||||
def get_int(self, name: str) -> int:
|
||||
"""Fetch integer value. Returns 0 if key not found."""
|
||||
if self._ht.__contains__(name) == 0:
|
||||
return 0
|
||||
ptr: t.CPtr = self._ht[name]
|
||||
return c.Deref(t.CInt(t.CUInt64T(ptr), t.CPtr))
|
||||
|
||||
def get_bool(self, name: str) -> INT:
|
||||
"""获取布尔值(返回 1 或 0)。键不存在返回 0。"""
|
||||
if self._ht.__contains__(name) == 0: return 0
|
||||
def get_bool(self, name: str) -> bool:
|
||||
"""Fetch boolean value. Returns false if key not found."""
|
||||
if self._ht.__contains__(name) == 0:
|
||||
return False
|
||||
ptr: t.CPtr = self._ht[name]
|
||||
return 1 if c.Deref(t.CInt(t.CUInt64T(ptr), t.CPtr)) != 0 else 0
|
||||
return c.Deref(t.CInt(t.CUInt64T(ptr), t.CPtr)) != 0
|
||||
|
||||
def has(self, name: str) -> bool:
|
||||
"""检查键是否存在。"""
|
||||
"""Check whether specified key exists."""
|
||||
return self._ht.__contains__(name) != 0
|
||||
|
||||
def _set_str(self, name: str, val: str):
|
||||
self._ht.set_str(name, val)
|
||||
|
||||
def _set_int(self, name: str, val: INT):
|
||||
def _set_int(self, name: str, val: int):
|
||||
self._ht.set_int(name, val)
|
||||
|
||||
def _set_bool(self, name: str, val: bool):
|
||||
@@ -114,21 +116,22 @@ class ParsedArgs:
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ArgumentParser — 命令行参数解析器
|
||||
# ArgumentParser — Command line argument parser
|
||||
# ============================================================
|
||||
|
||||
class ArgumentParser:
|
||||
_prog: str
|
||||
_description: str
|
||||
_args: Argument | t.CPtr
|
||||
_arg_count: INT
|
||||
_arg_count: int
|
||||
__mbuddy__: memhub.MemBuddy | t.CPtr
|
||||
|
||||
def __new__(self, prog: str = "", description: str = "",
|
||||
pool: memhub.MemBuddy | t.CPtr = None) -> t.CPtr:
|
||||
stdio.printf("[DBG-argparse] __new__ enter pool=%p\n", pool)
|
||||
mb: memhub.MemBuddy | t.CPtr = pool
|
||||
if mb is None: mb = _mbuddy
|
||||
if mb is None:
|
||||
mb = _mbuddy
|
||||
stdio.printf("[DBG-argparse] __new__ mb=%p\n", mb)
|
||||
ret: t.CPtr = mb.alloc(40)
|
||||
stdio.printf("[DBG-argparse] __new__ ret=%p\n", ret)
|
||||
@@ -138,7 +141,8 @@ class ArgumentParser:
|
||||
pool: memhub.MemBuddy | t.CPtr = None):
|
||||
stdio.printf("[DBG-argparse] __init__ enter self=%p pool=%p\n", self, pool)
|
||||
mb: memhub.MemBuddy | t.CPtr = pool
|
||||
if mb is None: mb = _mbuddy
|
||||
if mb is None:
|
||||
mb = _mbuddy
|
||||
stdio.printf("[DBG-argparse] __init__ mb=%p\n", mb)
|
||||
self.__mbuddy__ = mb
|
||||
self._prog = prog
|
||||
@@ -149,24 +153,25 @@ class ArgumentParser:
|
||||
stdio.printf("[DBG-argparse] __init__ after alloc _args=%p\n", self._args)
|
||||
|
||||
def add_argument(self, name: str = "", short: str = None,
|
||||
arg_type: INT = 0, default: INT = 0,
|
||||
arg_type: int = 0, default: int = 0,
|
||||
default_str: str = None, required: bool = False,
|
||||
action: INT = 0, help: str = None):
|
||||
"""注册一个命令行参数。
|
||||
action: int = 0, help: str = None):
|
||||
"""Register a command line argument.
|
||||
|
||||
Args:
|
||||
name: 参数名("--input" 或 "output")
|
||||
short: 短选项("-i"),可选
|
||||
arg_type: 类型(STRING/INT/BOOL)
|
||||
default: INT 默认值
|
||||
default_str: STRING 默认值
|
||||
required: 是否必须
|
||||
action: 动作(STORE/STORE_TRUE/STORE_FALSE/COUNT)
|
||||
help: 帮助文本
|
||||
name: Argument name ("--input" or positional "output")
|
||||
short: Short option ("-i"), optional
|
||||
arg_type: Data type (STRING/INT/BOOL)
|
||||
default: Default integer value
|
||||
default_str: Default string value
|
||||
required: Mandatory flag
|
||||
action: Action mode (STORE/STORE_TRUE/STORE_FALSE/COUNT)
|
||||
help: Help description text
|
||||
"""
|
||||
stdio.printf("[DBG-argparse] enter add_argument name=%s args_ptr=%p\n", name, self._args)
|
||||
if self._arg_count >= MAX_ARGS: return
|
||||
idx: INT = self._arg_count
|
||||
if self._arg_count >= MAX_ARGS:
|
||||
return
|
||||
idx: int = self._arg_count
|
||||
stdio.printf("[DBG-argparse] idx=%d sizeof(Argument)=%d\n", idx, Argument.__sizeof__())
|
||||
arg: Argument | t.CPtr = t.CPtr(t.CUInt64T(self._args) + idx * Argument.__sizeof__())
|
||||
stdio.printf("[DBG-argparse] arg ptr=%p\n", arg)
|
||||
@@ -180,7 +185,7 @@ class ArgumentParser:
|
||||
arg.default_str = default_str
|
||||
arg.required = required
|
||||
stdio.printf("[DBG-argparse] before dest logic\n")
|
||||
# 判断是否位置参数
|
||||
# Determine positional flag
|
||||
if name is not None and name[0] != '-':
|
||||
arg.is_positional = True
|
||||
arg.dest = name
|
||||
@@ -194,12 +199,12 @@ class ArgumentParser:
|
||||
self._arg_count = idx + 1
|
||||
stdio.printf("[DBG-argparse] exit add_argument\n")
|
||||
|
||||
def _get_arg(self, idx: INT) -> Argument | t.CPtr:
|
||||
def _get_arg(self, idx: int) -> Argument | t.CPtr:
|
||||
return t.CPtr(t.CUInt64T(self._args) + idx * Argument.__sizeof__())
|
||||
|
||||
def _find_long(self, token: str) -> INT:
|
||||
"""精确匹配长选项名"""
|
||||
i: INT = 0
|
||||
def _find_long(self, token: str) -> int:
|
||||
"""Exact match for long option name"""
|
||||
i: int = 0
|
||||
while i < self._arg_count:
|
||||
arg: Argument | t.CPtr = self._get_arg(i)
|
||||
if string.strcmp(arg.name, token) == 0:
|
||||
@@ -207,20 +212,20 @@ class ArgumentParser:
|
||||
i += 1
|
||||
return -1
|
||||
|
||||
def _find_long_prefix(self, token: str) -> INT:
|
||||
"""匹配 --name=value 中的 name 前缀"""
|
||||
i: INT = 0
|
||||
def _find_long_prefix(self, token: str) -> int:
|
||||
"""Match prefix for --name=value syntax"""
|
||||
i: int = 0
|
||||
while i < self._arg_count:
|
||||
arg: Argument | t.CPtr = self._get_arg(i)
|
||||
name_len: INT = string.strlen(arg.name)
|
||||
name_len: int = string.strlen(arg.name)
|
||||
if string.strncmp(token, arg.name, name_len) == 0:
|
||||
if token[name_len] == '=':
|
||||
return i
|
||||
i += 1
|
||||
return -1
|
||||
|
||||
def _find_short(self, token: str) -> INT:
|
||||
i: INT = 0
|
||||
def _find_short(self, token: str) -> int:
|
||||
i: int = 0
|
||||
while i < self._arg_count:
|
||||
arg: Argument | t.CPtr = self._get_arg(i)
|
||||
if arg.short_name is not None:
|
||||
@@ -229,9 +234,9 @@ class ArgumentParser:
|
||||
i += 1
|
||||
return -1
|
||||
|
||||
def _find_positional(self, pos_idx: INT) -> INT:
|
||||
count: INT = 0
|
||||
i: INT = 0
|
||||
def _find_positional(self, pos_idx: int) -> int:
|
||||
count: int = 0
|
||||
i: int = 0
|
||||
while i < self._arg_count:
|
||||
arg: Argument | t.CPtr = self._get_arg(i)
|
||||
if arg.is_positional:
|
||||
@@ -248,11 +253,8 @@ class ArgumentParser:
|
||||
elif arg.arg_type == STRING:
|
||||
args._set_str(arg.dest, value)
|
||||
elif arg.arg_type == BOOL:
|
||||
v: INT = string.atoi(value)
|
||||
if v != 0:
|
||||
args._set_bool(arg.dest, True)
|
||||
else:
|
||||
args._set_bool(arg.dest, False)
|
||||
v: int = string.atoi(value)
|
||||
args._set_bool(arg.dest, v != 0)
|
||||
|
||||
def _apply_action(self, args: ParsedArgs | t.CPtr, arg: Argument | t.CPtr):
|
||||
if arg.action == STORE_TRUE:
|
||||
@@ -260,25 +262,27 @@ class ArgumentParser:
|
||||
elif arg.action == STORE_FALSE:
|
||||
args._set_bool(arg.dest, False)
|
||||
elif arg.action == COUNT:
|
||||
cur: INT = args.get_int(arg.dest)
|
||||
cur: int = args.get_int(arg.dest)
|
||||
args._set_int(arg.dest, cur + 1)
|
||||
|
||||
def parse_args(self, argc: INT, argv: str | t.CPtr) -> ParsedArgs | t.CPtr:
|
||||
"""解析命令行参数。
|
||||
def parse_args(self, argc: int, argv: str | t.CPtr) -> ParsedArgs | t.CPtr:
|
||||
"""Parse command line arguments.
|
||||
|
||||
Args:
|
||||
argc: 参数个数
|
||||
argv: 参数数组(char**,argv[0] 为程序名)
|
||||
argc: Argument count
|
||||
argv: Argument array (char**, argv[0] = program name)
|
||||
Returns:
|
||||
ParsedArgs 指针,失败返回 None
|
||||
Pointer to ParsedArgs; returns None on failure
|
||||
"""
|
||||
if self.__mbuddy__ is None: return None
|
||||
if self.__mbuddy__ is None:
|
||||
return None
|
||||
|
||||
args: ParsedArgs | t.CPtr = ParsedArgs(self.__mbuddy__)
|
||||
if args is None: return None
|
||||
if args is None:
|
||||
return None
|
||||
|
||||
# 初始化默认值
|
||||
i: INT = 0
|
||||
# Initialize default values
|
||||
i: int = 0
|
||||
while i < self._arg_count:
|
||||
arg: Argument | t.CPtr = self._get_arg(i)
|
||||
if arg.action == STORE:
|
||||
@@ -294,22 +298,22 @@ class ArgumentParser:
|
||||
args._set_int(arg.dest, 0)
|
||||
i += 1
|
||||
|
||||
# 解析 argv
|
||||
idx: INT = 1
|
||||
pos_idx: INT = 0
|
||||
# Traverse argv
|
||||
idx: int = 1
|
||||
pos_idx: int = 0
|
||||
token: str = None
|
||||
found: INT = 0
|
||||
found: int = 0
|
||||
arg: Argument | t.CPtr = None
|
||||
value: str = None
|
||||
entry: str | t.CPtr = None
|
||||
name_len: INT = 0
|
||||
|
||||
while idx < argc:
|
||||
entry = t.CPtr(t.CUInt64T(argv) + idx * 8)
|
||||
token = entry[0]
|
||||
if token is None: break
|
||||
if token is None:
|
||||
break
|
||||
|
||||
# "--" 结束符:后续全部为位置参数
|
||||
# "--" terminator: all subsequent tokens become positional arguments
|
||||
if token[0] == '-' and token[1] == '-' and token[2] == 0:
|
||||
idx += 1
|
||||
while idx < argc:
|
||||
@@ -326,9 +330,8 @@ class ArgumentParser:
|
||||
idx += 1
|
||||
break
|
||||
|
||||
# 长选项 --name 或 --name=value
|
||||
# Long option --name or --name=value
|
||||
if token[0] == '-' and token[1] == '-':
|
||||
# 检查是否含 =
|
||||
has_eq: bool = False
|
||||
p: str = token
|
||||
while p[0] != 0:
|
||||
@@ -338,32 +341,28 @@ class ArgumentParser:
|
||||
p += 1
|
||||
|
||||
if has_eq:
|
||||
# --name=value
|
||||
# --name=value syntax
|
||||
found = self._find_long_prefix(token)
|
||||
if found < 0:
|
||||
stdio.printf(
|
||||
"error: unrecognized argument '%s'\n", token)
|
||||
stdio.printf("error: unrecognized argument '%s'\n", token)
|
||||
release(args)
|
||||
return None
|
||||
arg = self._get_arg(found)
|
||||
# 提取 = 后的值
|
||||
arg_name_len: INT = string.strlen(arg.name)
|
||||
arg_name_len: int = string.strlen(arg.name)
|
||||
value = token + arg_name_len + 1
|
||||
self._store_value(args, arg, value)
|
||||
idx += 1
|
||||
else:
|
||||
# --name(值在下一个 argv 或标志)
|
||||
# --name with value in next token or flag action
|
||||
found = self._find_long(token)
|
||||
if found < 0:
|
||||
stdio.printf(
|
||||
"error: unrecognized argument '%s'\n", token)
|
||||
stdio.printf("error: unrecognized argument '%s'\n", token)
|
||||
release(args)
|
||||
return None
|
||||
arg = self._get_arg(found)
|
||||
if arg.action == STORE:
|
||||
if idx + 1 >= argc:
|
||||
stdio.printf(
|
||||
"error: %s requires a value\n", arg.name)
|
||||
stdio.printf("error: %s requires a value\n", arg.name)
|
||||
release(args)
|
||||
return None
|
||||
entry = t.CPtr(t.CUInt64T(argv) + (idx + 1) * 8)
|
||||
@@ -374,19 +373,17 @@ class ArgumentParser:
|
||||
self._apply_action(args, arg)
|
||||
idx += 1
|
||||
|
||||
# 短选项 -x
|
||||
# Short option -x
|
||||
elif token[0] == '-':
|
||||
found = self._find_short(token)
|
||||
if found < 0:
|
||||
stdio.printf(
|
||||
"error: unrecognized argument '%s'\n", token)
|
||||
stdio.printf("error: unrecognized argument '%s'\n", token)
|
||||
release(args)
|
||||
return None
|
||||
arg = self._get_arg(found)
|
||||
if arg.action == STORE:
|
||||
if idx + 1 >= argc:
|
||||
stdio.printf(
|
||||
"error: %s requires a value\n", arg.name)
|
||||
stdio.printf("error: %s requires a value\n", arg.name)
|
||||
release(args)
|
||||
return None
|
||||
entry = t.CPtr(t.CUInt64T(argv) + (idx + 1) * 8)
|
||||
@@ -397,12 +394,11 @@ class ArgumentParser:
|
||||
self._apply_action(args, arg)
|
||||
idx += 1
|
||||
|
||||
# 位置参数
|
||||
# Positional argument
|
||||
else:
|
||||
found = self._find_positional(pos_idx)
|
||||
if found < 0:
|
||||
stdio.printf(
|
||||
"error: unexpected argument '%s'\n", token)
|
||||
stdio.printf("error: unexpected argument '%s'\n", token)
|
||||
release(args)
|
||||
return None
|
||||
arg = self._get_arg(found)
|
||||
@@ -410,15 +406,13 @@ class ArgumentParser:
|
||||
pos_idx += 1
|
||||
idx += 1
|
||||
|
||||
# 检查必须参数
|
||||
# Validate required arguments
|
||||
i = 0
|
||||
while i < self._arg_count:
|
||||
arg = self._get_arg(i)
|
||||
if arg.required:
|
||||
if not args.has(arg.dest):
|
||||
stdio.printf(
|
||||
"error: missing required argument '%s'\n",
|
||||
arg.name)
|
||||
stdio.printf("error: missing required argument '%s'\n", arg.name)
|
||||
release(args)
|
||||
return None
|
||||
i += 1
|
||||
@@ -426,17 +420,18 @@ class ArgumentParser:
|
||||
return args
|
||||
|
||||
def print_help(self):
|
||||
"""打印帮助信息"""
|
||||
"""Print complete help message"""
|
||||
stdio.printf("usage: %s [options]\n", self._prog)
|
||||
if self._description is not None and self._description[0] != 0:
|
||||
stdio.printf("\n%s\n", self._description)
|
||||
stdio.printf("\npositional arguments:\n")
|
||||
i: INT = 0
|
||||
i: int = 0
|
||||
while i < self._arg_count:
|
||||
arg: Argument | t.CPtr = self._get_arg(i)
|
||||
if arg.is_positional:
|
||||
ht: str = arg.help_text
|
||||
if ht is None: ht = ""
|
||||
if ht is None:
|
||||
ht = ""
|
||||
stdio.printf(" %-20s %s\n", arg.name, ht)
|
||||
i += 1
|
||||
stdio.printf("\noptional arguments:\n")
|
||||
@@ -445,27 +440,29 @@ class ArgumentParser:
|
||||
arg = self._get_arg(i)
|
||||
if not arg.is_positional:
|
||||
ht: str = arg.help_text
|
||||
if ht is None: ht = ""
|
||||
if ht is None:
|
||||
ht = ""
|
||||
if arg.short_name is not None:
|
||||
stdio.printf(" %s, %-18s %s\n",
|
||||
arg.short_name, arg.name, ht)
|
||||
stdio.printf(" %s, %-18s %s\n", arg.short_name, arg.name, ht)
|
||||
else:
|
||||
stdio.printf(" %-22s %s\n", arg.name, ht)
|
||||
i += 1
|
||||
|
||||
def print_usage(self):
|
||||
"""打印用法简述"""
|
||||
"""Print brief usage summary"""
|
||||
stdio.printf("usage: %s [options]\n", self._prog)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# release — 释放 ParsedArgs 及其内部资源
|
||||
# release — Release ParsedArgs and all internal resources
|
||||
# ============================================================
|
||||
|
||||
def release(args: ParsedArgs | t.CPtr):
|
||||
"""释放 ParsedArgs 对象及其内部 HashTable。"""
|
||||
if args is None: return
|
||||
if args.__mbuddy__ is None: return
|
||||
"""Free ParsedArgs object and its inner HashTable resources."""
|
||||
if args is None:
|
||||
return
|
||||
if args.__mbuddy__ is None:
|
||||
return
|
||||
if args._ht is not None:
|
||||
if args._ht.__slots__ is not None:
|
||||
args.__mbuddy__.free(args._ht.__slots__)
|
||||
|
||||
Reference in New Issue
Block a user