Files
Viper_VET/App/lib/VLog.vp
T
TermiNexus 02df100204 chore(vet): 初始化 VET 仓(Viper Environment Tool)
首次入库,远端 https://git.gvsds.com/GVSDS/Viper_VET 。

19 个文件全部为源码/配置,无构建产物:
  App/main.vp、App/lib/*.vp(VCache / VCheck / VCli / VDirs / VFs / VGuard /
    VGuid / VJson / VLog / VPe / VProc / VScan / __init__)
  1.json、LICENSE、README.md、project.vpj、.gitignore

既有 .gitignore 已覆盖本仓的产物目录(**/output/、**/temp/、**/.tpv_build/)
与 *.exe / *.obj / *.o / *.img / *.iso / __pycache__/ / .cache/;
实测 `git add -A --dry-run` 仅 19 个文件、零产物混入,故未改动 .gitignore。
2026-09-29 15:20:13 +08:00

243 lines
8.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
from stdint import *
import stdlib
import string
import viperlib
import w32.win32file as wf
import w32.win32base as wb
# ============================================================
# VLog - 输出原语(全部人类可读日志走 stderr;stdout 只留 JSON)
#
# 本模块从原 App/main.vp 的 [stderr 日志] 段整体平移,行为不变:
# * LogStr/LogFmt1/2/3/LogFmtS1/S2/LogFmtIS 沿用原实现与固定元数转发风格;
# * 本轮新增 LogFmt4(进度行需要 4 个整数参数)与两个时间戳辅助。
#
# 日志详细度(本轮新增):模块级开关 Verbose_Enabled(0=默认安静,1=--verbose)。
# * 默认安静:只保留"启动摘要 / 心跳确认提示与失败原因 / 警告与致命错误 / 轮末一行";
# 过程细节(进度行、扫描根进出、逐条 [reject]/[pe]、逐次 --version 探测、目录表逐条
# 列举、轮末的"下轮开始")一律不输出。
# * VerboseStr / VerboseFmt1/2/3/4 / VerboseFmtS1/S2/VerboseFmtIS 是 Log* 的兄弟函数:
# 开关关闭时直接返回(不格式化、不写 stderr),打开时逐字转发给对应 Log*。
# 调用点只写 Verbose*,"开关判断"集中在本模块,不散落到各调用点。
# * 取值由 VCli 解析 --verbose 后经 SetVerbose 在**任何日志之前**设置
# (scan:App/main.vp:VCli.ParseScanArgs 之后;看门狗:confirm-watch 参数解析之后)。
# 依赖(本仓既有):
# wf.GetStdHandle(includes/w32/win32file.vp:120)、wf.WriteFile(:91)、
# wf.STD_ERROR_HANDLE(:46)、wf.STD_OUTPUT_HANDLE(:45)、wb.INVALID_HANDLE_VALUE(:9)、
# wb.GetLocalTime(includes/w32/win32base.vp:72)、wb.SystemTimeToFileTime(:74)、
# wb.FileTimeToSystemTime(:73)、wb.SYSTEMTIME(:40)、wb.FILETIME(:36)、
# viperlib.snprintf(includes/viperlib.vp:25)、string.strlen(includes/string.vp:69)。
# ============================================================
LOG_CAP: t.CDefine = 4096 # 日志格式化缓冲
Log_Buffer: bytes = None # 日志格式化缓冲(stdlib.malloc,进程生命周期)
# 字面量/已格式化字节串原样写 stderr(不自动追加换行)
def LogStr(S: str):
if S is None:
return
H: wb.HANDLE = wf.GetStdHandle(wf.STD_ERROR_HANDLE)
if H is None or H == wb.INVALID_HANDLE_VALUE:
return
n: t.CSizeT = string.strlen(S)
if n == 0:
return
bw: ULONG = 0
wf.WriteFile(H, S, ULONG(n), t.CPtr(c.Addr(bw)), None)
def LogInit() -> int:
global Log_Buffer
Log_Buffer = stdlib.malloc(LOG_CAP)
if Log_Buffer is None:
return 0
Log_Buffer[0] = 0
return 1
# 固定元数的格式化转发(非 varargs 函数 ⇒ 不引入自定义可变参数风险):
# 内部调用既有的 viperlib.snprintf,把格式化结果写 stderr。
def LogFmt1(Fmt: str, A: t.CSizeT) -> int:
if Log_Buffer is None:
return 0
viperlib.snprintf(Log_Buffer, t.CSizeT(LOG_CAP), Fmt, A)
LogStr(str(Log_Buffer))
return 1
def LogFmt2(Fmt: str, A: t.CSizeT, B: t.CSizeT) -> int:
if Log_Buffer is None:
return 0
viperlib.snprintf(Log_Buffer, t.CSizeT(LOG_CAP), Fmt, A, B)
LogStr(str(Log_Buffer))
return 1
def LogFmt3(Fmt: str, A: t.CSizeT, B: t.CSizeT, C: t.CSizeT) -> int:
if Log_Buffer is None:
return 0
viperlib.snprintf(Log_Buffer, t.CSizeT(LOG_CAP), Fmt, A, B, C)
LogStr(str(Log_Buffer))
return 1
# 需求 3:扫盘进度行需要 4 个整数(r/dir/file/cand)
def LogFmt4(Fmt: str, A: t.CSizeT, B: t.CSizeT, C: t.CSizeT, D: t.CSizeT) -> int:
if Log_Buffer is None:
return 0
viperlib.snprintf(Log_Buffer, t.CSizeT(LOG_CAP), Fmt, A, B, C, D)
LogStr(str(Log_Buffer))
return 1
def LogFmtS1(Fmt: str, A: str) -> int:
if Log_Buffer is None:
return 0
viperlib.snprintf(Log_Buffer, t.CSizeT(LOG_CAP), Fmt, A)
LogStr(str(Log_Buffer))
return 1
def LogFmtS2(Fmt: str, A: str, B: str) -> int:
if Log_Buffer is None:
return 0
viperlib.snprintf(Log_Buffer, t.CSizeT(LOG_CAP), Fmt, A, B)
LogStr(str(Log_Buffer))
return 1
def LogFmtIS(Fmt: str, A: t.CSizeT, B: str) -> int:
if Log_Buffer is None:
return 0
viperlib.snprintf(Log_Buffer, t.CSizeT(LOG_CAP), Fmt, A, B)
LogStr(str(Log_Buffer))
return 1
# ============================================================
# verbose 开关与"仅 verbose 才输出"的兄弟函数
# * 开关集中在 Verbose_Enabled 一处;调用点只写 Verbose*,不写 if。
# * 关闭时直接返回 0(连格式化都不做),打开时逐字转发给对应 Log*。
# * 返回码与 Log* 一致(1=已写出,0=未写出/失败)。
# ============================================================
Verbose_Enabled: int = 0 # 0=默认安静;1=--verbose
def SetVerbose(V: int):
global Verbose_Enabled
Verbose_Enabled = V
def VerboseOn() -> int:
return Verbose_Enabled
def VerboseStr(S: str) -> int:
if Verbose_Enabled == 0:
return 0
LogStr(S)
return 1
def VerboseFmt1(Fmt: str, A: t.CSizeT) -> int:
if Verbose_Enabled == 0:
return 0
LogFmt1(Fmt, A)
return 1
def VerboseFmt2(Fmt: str, A: t.CSizeT, B: t.CSizeT) -> int:
if Verbose_Enabled == 0:
return 0
LogFmt2(Fmt, A, B)
return 1
def VerboseFmt3(Fmt: str, A: t.CSizeT, B: t.CSizeT, C: t.CSizeT) -> int:
if Verbose_Enabled == 0:
return 0
LogFmt3(Fmt, A, B, C)
return 1
def VerboseFmt4(Fmt: str, A: t.CSizeT, B: t.CSizeT, C: t.CSizeT, D: t.CSizeT) -> int:
if Verbose_Enabled == 0:
return 0
LogFmt4(Fmt, A, B, C, D)
return 1
def VerboseFmtS1(Fmt: str, A: str) -> int:
if Verbose_Enabled == 0:
return 0
LogFmtS1(Fmt, A)
return 1
def VerboseFmtS2(Fmt: str, A: str, B: str) -> int:
if Verbose_Enabled == 0:
return 0
LogFmtS2(Fmt, A, B)
return 1
def VerboseFmtIS(Fmt: str, A: t.CSizeT, B: str) -> int:
if Verbose_Enabled == 0:
return 0
LogFmtIS(Fmt, A, B)
return 1
# stdout 原样写(scan 模式只输出 JSON)
def StdoutWrite(S: str):
if S is None:
return
H: wb.HANDLE = wf.GetStdHandle(wf.STD_OUTPUT_HANDLE)
if H is None or H == wb.INVALID_HANDLE_VALUE:
return
n: t.CSizeT = string.strlen(S)
if n == 0:
return
bw: ULONG = 0
wf.WriteFile(H, S, ULONG(n), t.CPtr(c.Addr(bw)), None)
# ============================================================
# 时间戳(需求 3:轮次开始/下轮开始)
# 用 Win32 本地时间;AddMs 通过 FILETIME(100ns) 加法后回转 SYSTEMTIME。
# 依据:wb.FILETIME 为 {dwLowDateTime,dwHighDateTime}(win32base.vp:36),
# FILETIME 单位 100ns(Win32 规范),故 AddMs*10000 为增量。
# ============================================================
def TimeStampNow(Out: bytes, Cap: int) -> int:
St: wb.SYSTEMTIME = wb.SYSTEMTIME()
wb.GetLocalTime(t.CPtr(c.Addr(St)))
viperlib.snprintf(Out, t.CSizeT(Cap), "%04u-%02u-%02u %02u:%02u:%02u",
t.CUInt32T(St.wYear), t.CUInt32T(St.wMonth), t.CUInt32T(St.wDay),
t.CUInt32T(St.wHour), t.CUInt32T(St.wMinute), t.CUInt32T(St.wSecond))
return 1
def TimeStampAfter(Out: bytes, Cap: int, AddMs: t.CSizeT) -> int:
St: wb.SYSTEMTIME = wb.SYSTEMTIME()
wb.GetLocalTime(t.CPtr(c.Addr(St)))
Ft: wb.FILETIME = wb.FILETIME()
if wb.SystemTimeToFileTime(t.CPtr(c.Addr(St)), t.CPtr(c.Addr(Ft))) == 0:
return TimeStampNow(Out, Cap)
Ticks: ULONGLONG = (ULONGLONG(Ft.dwHighDateTime) << 32) | ULONGLONG(Ft.dwLowDateTime)
Ticks = Ticks + (ULONGLONG(AddMs) * ULONGLONG(10000))
Ft.dwLowDateTime = DWORD(Ticks & ULONGLONG(0xFFFFFFFF))
Ft.dwHighDateTime = DWORD(Ticks >> 32)
St2: wb.SYSTEMTIME = wb.SYSTEMTIME()
if wb.FileTimeToSystemTime(t.CPtr(c.Addr(Ft)), t.CPtr(c.Addr(St2))) == 0:
return TimeStampNow(Out, Cap)
viperlib.snprintf(Out, t.CSizeT(Cap), "%04u-%02u-%02u %02u:%02u:%02u",
t.CUInt32T(St2.wYear), t.CUInt32T(St2.wMonth), t.CUInt32T(St2.wDay),
t.CUInt32T(St2.wHour), t.CUInt32T(St2.wMinute), t.CUInt32T(St2.wSecond))
return 1