Files
Viper_VRTE/viperlib.vp
T
TermiNexus cc7cfdb4af fix(mlirlite): alias 表按需扩容;工厂改 new memgr;define 位宽/截断配套
- mlirlite/__function.vp:_MlirAliasAdd 的 512 条硬上限改为 _MlirAliasGrow 池内翻倍扩容,不再把资源限制当编译错误
- mlirlite 类型工厂改 new memgr(pool) 返回值(消除栈逃逸);__module.vp 补 triple/datalayout
- viperlib.get_digit_count 用 uint(base) 显式声明无符号除法语义(新 AugAssign 符号规则)
- string.vp:strcpy/strcat/strncpy/strncat/memset/memset32/memcpy/memmove 加 @life(noescape(...))
2026-10-12 12:38:15 +08:00

1384 lines
58 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 viperio
from stdarg import arg
define TEMP_BUF_SIZE = 68
def get_digit_count(num: uint, base: int) -> int:
count: int = 0
if num == 0: return 1
while num > 0:
count += 1
# 显式收窄口径:目标 num 是无符号、base 是有符号,按新规则必须显式声明用无符号语义
# (base 恒为 2/10/16 等正整数;若传负值,uint(base) 会得到其无符号位型,语义与旧隐式行为一致)。
num //= uint(base)
return count
# Return type must be int, matching the CRT `sprintf` and includes/stdio.vp;
# return vsnprintf's write length directly (consistent with the CRT).
export def sprintf(buf: str, rule: str, *args) -> int:
if buf is None or rule is None: return 0
return vsnprintf(buf, 0x7FFFFFFF, rule, args)
def vsprintf(buf: str, rule: str, *args) -> int:
if buf is None or rule is None: return 0
return vsnprintf(buf, 0x7FFFFFFF, rule, args)
export def snprintf(buf: str, size: sizet, fmt: str, *args) -> int:
if fmt is None: return 0
if buf is None or size == 0: return vsnprintf(None, 0, fmt, args)
ret: int = vsnprintf(buf, size, fmt, args)
return ret
# Check float special values (IEEE 754): 0=normal, 1=+inf, 2=-inf, 3=nan.
# Do NOT read the bit pattern via `*&fbits = *&fv`: the assignment is silently dropped (fbits stays 0), so this function would always return 0 and inf would spin forever in the float formatting loops. Use pure float semantics instead (NaN: fv != fv; ±inf: fv - fv is NaN, finite gives 0.0).
def _check_special_float(fv: double) -> int:
if fv != fv: return 3
diff: double = fv - fv
if diff != diff:
if fv < 0.0: return 2
return 1
return 0
# The 4th parameter MUST stay named `args`: the printf wrappers forward their own va_list pointer
# here (vprintf style), and the `arg()` sugar resolves the forwarded va_list by that name.
export def vsnprintf(buf: bytes, size: sizet, fmt: str, args: str) -> int:
if fmt is None: return 0
# Length detection mode: when buf is None, only calculate the formatted length, without actually writing
# _step=0 makes ptr not advance, repeatedly writing the same dummy byte (harmless), write_count accumulates correctly
count_mode: int = 0
_step: int = 1
_dummy: char = '\0'
if buf is None or size == 0:
count_mode = 1
_step = 0
buf = &_dummy
size = 0x7FFFFFFF
ptr: str = buf
write_count: int = 0
temp: [68]char
temp[0] = '\t'
while *fmt != 0 and write_count < size - 1:
if *fmt != 37:
ptr[0] = *fmt
write_count += 1
ptr += _step
fmt += 1
else:
fmt += 1
if *fmt == 0: break
width: int = 0
pad_zero: int = 0
left_align: int = 0
show_sign: int = 0
space_sign: int = 0
alt_form: int = 0
precision: int = -1
is_long: int = 0
is_long_long: int = 0
is_size: int = 0
is_short: int = 0
is_char: int = 0
while True:
if *fmt == 45:
left_align = 1
fmt += 1
elif *fmt == 48:
pad_zero = 1
fmt += 1
elif *fmt == 43:
show_sign = 1
fmt += 1
elif *fmt == 32:
space_sign = 1
fmt += 1
elif *fmt == 35:
alt_form = 1
fmt += 1
else: break
if show_sign: space_sign = 0
while *fmt >= 48 and *fmt <= 57:
width = width * 10 + (*fmt - 48)
fmt += 1
if *fmt == 46:
fmt += 1
precision = 0
while *fmt >= 48 and *fmt <= 57:
precision = precision * 10 + (*fmt - 48)
fmt += 1
if left_align: pad_zero = 0
if *fmt == 108:
is_long = 1
fmt += 1
if *fmt == 108:
is_long_long = 1
is_long = 0
fmt += 1
elif *fmt == 104:
is_short = 1
fmt += 1
if *fmt == 104:
is_char = 1
is_short = 0
fmt += 1
elif *fmt == 122:
is_size = 1
fmt += 1
elif *fmt == 106:
is_long_long = 1
fmt += 1
elif *fmt == 116:
is_long = 1
fmt += 1
if *fmt == 99:
if write_count < size - 1:
ptr_i: int = arg(int)
ptr[0] = char(ptr_i)
write_count += 1
ptr += _step
else:
ptr_i: int = arg(int)
elif *fmt == 115:
s: str = arg(rawptr)
if s is None: s = "(None)"
slen: int = 0
sc: str = s
while *sc != 0:
slen += 1
sc += 1
if not left_align and width > slen:
pad_count: int = width - slen
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
while *s != 0 and write_count < size - 1:
ptr[0] = *s
write_count += 1
ptr += _step
s += 1
if left_align and width > slen:
pad_count = width - slen
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 100 or *fmt == 105:
if is_long_long or is_size or is_long:
num_l: int64 = arg(int64)
else:
num_l: int64 = int64(arg(int))
if is_char:
num_l = int64(char(num_l))
elif is_short:
num_l = int64(short(num_l))
sign: int = 0
if num_l < 0:
sign = 1
if num_l == (-9223372036854775807 - 1):
u_num: uint64 = uint64(0x8000000000000000)
else:
u_num: uint64 = uint64(-num_l)
else:
u_num: uint64 = uint64(num_l)
if show_sign: sign = 2
elif space_sign: sign = 3
i: int = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
temp[i] = char(u_num % 10 + 48)
i += 1
u_num //= 10
if u_num <= 0: break
if sign == 1 and i < TEMP_BUF_SIZE - 1:
temp[i] = 45
i += 1
elif sign == 2 and i < TEMP_BUF_SIZE - 1:
temp[i] = 43
i += 1
elif sign == 3 and i < TEMP_BUF_SIZE - 1:
temp[i] = 32
i += 1
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 117:
if is_long or is_long_long or is_size:
u_num_l: uint64 = arg(uint64)
else:
u_num_l: uint64 = uint64(uint(arg()))
i = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
temp[i] = char(u_num_l % 10 + 48)
i += 1
u_num_l //= 10
if u_num_l <= 0: break
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 120:
if is_long or is_long_long or is_size:
u_num_l: uint64 = arg(uint64)
else:
u_num_l: uint64 = uint64(uint(arg()))
is_nonzero: int = 0
if u_num_l != 0:
is_nonzero = 1
i = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
digit: int = int(u_num_l % 16)
if digit < 10:
temp[i] = char(digit + 48)
else:
temp[i] = char(digit - 10 + 97)
u_num_l //= 16
i += 1
if u_num_l <= 0: break
digit_count: int = i
prefix_len: int = 0
if alt_form and is_nonzero:
prefix_len = 2
effective_len: int = digit_count + prefix_len
if not left_align and not pad_zero and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if prefix_len > 0:
if write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = 120
write_count += 1
ptr += _step
if pad_zero and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
if left_align and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 88:
if is_long or is_long_long or is_size:
u_num_l: uint64 = arg()
else:
u_num_l: uint64 = uint64(uint(arg()))
is_nonzero = 0
if u_num_l != 0:
is_nonzero = 1
i = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
digit = int(u_num_l % 16)
if digit < 10:
temp[i] = char(digit + 48)
else:
temp[i] = char(digit - 10 + 65)
u_num_l //= 16
i += 1
if u_num_l <= 0: break
digit_count = i
prefix_len = 0
if alt_form and is_nonzero:
prefix_len = 2
effective_len = digit_count + prefix_len
if not left_align and not pad_zero and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if prefix_len > 0:
if write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = 88
write_count += 1
ptr += _step
if pad_zero and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
if left_align and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 111:
if is_long or is_long_long or is_size:
u_num_l: uint64 = arg(uint64)
else:
u_num_l: uint64 = uint64(uint(arg()))
if is_char:
u_num_l = uint64(char(u_num_l))
elif is_short:
u_num_l = uint64(short(u_num_l))
i = 0
if u_num_l == 0 and not alt_form:
temp[0] = 48
i = 1
else:
while True:
if i >= TEMP_BUF_SIZE - 1: break
temp[i] = char(u_num_l % 8 + 48)
i += 1
u_num_l //= 8
if u_num_l <= 0: break
if alt_form and i < TEMP_BUF_SIZE - 1:
temp[i] = 48
i += 1
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 98:
if is_long or is_long_long or is_size:
u_num_l: uint64 = arg(uint64)
else:
u_num_l: uint64 = uint64(uint(arg()))
if is_char:
u_num_l = uint64(char(u_num_l))
elif is_short:
u_num_l = uint64(short(u_num_l))
i = 0
if u_num_l == 0:
temp[0] = 48
i = 1
else:
while True:
if i >= TEMP_BUF_SIZE - 1: break
temp[i] = char(u_num_l % 2 + 48)
i += 1
u_num_l //= 2
if u_num_l <= 0: break
if alt_form and i < TEMP_BUF_SIZE - 1:
temp[i] = 98
i += 1
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 112:
ptr_val: uint64 = uint64(arg(rawptr))
if ptr_val == 0:
temp[0] = 40
temp[1] = 110
temp[2] = 105
temp[3] = 108
temp[4] = 41
i = 5
else:
u_num_l = ptr_val
i = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
digit = int(u_num_l % 16)
if digit < 10:
temp[i] = char(digit + 48)
else:
temp[i] = char(digit - 10 + 97)
u_num_l //= 16
i += 1
if u_num_l <= 0: break
if i < TEMP_BUF_SIZE - 1:
temp[i] = 120
i += 1
if i < TEMP_BUF_SIZE - 1:
temp[i] = 48
i += 1
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 102 or *fmt == 70:
f_upper: int = 1 if *fmt == 70 else 0
if precision < 0: precision = 6
fv: double = arg(double)
f_sp: int = _check_special_float(fv)
if f_sp != 0:
f_sgn_len: int = 0
if f_sp == 2:
f_sgn_len = 1
elif f_sp == 1 and show_sign:
f_sgn_len = 1
elif f_sp == 1 and space_sign:
f_sgn_len = 1
f_total_len: int = f_sgn_len + 3
if not left_align and width > f_total_len:
f_pad: int = width - f_total_len
while f_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
f_pad -= 1
if f_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif f_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif f_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
fi_c: int = 0
while fi_c < 3 and write_count < size - 1:
fc: int = 0
if f_sp == 3:
# nan
if fi_c == 0:
fc = 110
elif fi_c == 1:
fc = 97
else:
fc = 110
else:
# inf (f_sp==1 +inf or f_sp==2 -inf)
if fi_c == 0:
fc = 105
elif fi_c == 1:
fc = 110
else:
fc = 102
if f_upper and fc >= 97 and fc <= 122:
fc -= 32
ptr[0] = char(fc)
write_count += 1
ptr += _step
fi_c += 1
if left_align and width > f_total_len:
f_pad = width - f_total_len
while f_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
f_pad -= 1
fmt += 1
continue
if fv < 0.0:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
fv = 0.0 - fv
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
di: int = 0
work: double = fv
if work < 1.0:
temp[0] = 48
di = 1
else:
scale: double = 1.0
# Upper-bound guard: inf makes `work >= scale*10.0` always true; finite values need at most 308 iterations
scale_guard: int = 0
while work >= scale * 10.0 and scale_guard < 400:
scale *= 10.0
scale_guard += 1
while scale >= 1.0 and di < TEMP_BUF_SIZE - 1:
d: int = int(work / scale)
if d > 9: d = 9
temp[di] = char(d + 48)
di += 1
work = work - double(d) * scale
scale /= 10.0
frac_val: double = work
for p in range(int(precision)):
frac_val *= 10.0
frac_part: uint64 = uint64(frac_val + 0.5)
f_total: int = di + (precision + 1 if precision > 0 else 0)
if not left_align and not pad_zero and width > f_total:
pad_count = width - f_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if pad_zero and width > f_total:
pad_count = width - f_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
while di > 0 and write_count < size - 1:
di -= 1
ptr[0] = temp[di]
write_count += 1
ptr += _step
if precision > 0:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
fi: int = 0
while fi < precision and fi < TEMP_BUF_SIZE - 1:
temp[fi] = char(frac_part % 10 + 48)
fi += 1
frac_part //= 10
while fi < precision and fi < TEMP_BUF_SIZE - 1:
temp[fi] = 48
fi += 1
while fi > 0 and write_count < size - 1:
fi -= 1
ptr[0] = temp[fi]
write_count += 1
ptr += _step
elif alt_form:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
if left_align and width > f_total:
pad_count = width - f_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 101 or *fmt == 69:
if precision < 0: precision = 6
fv: double = arg(double)
e_upper: int = 1 if *fmt == 69 else 0
e_sp: int = _check_special_float(fv)
if e_sp != 0:
e_sgn_len: int = 0
if e_sp == 2:
e_sgn_len = 1
elif e_sp == 1 and show_sign:
e_sgn_len = 1
elif e_sp == 1 and space_sign:
e_sgn_len = 1
e_total_len: int = e_sgn_len + 3
if not left_align and width > e_total_len:
e_pad: int = width - e_total_len
while e_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
e_pad -= 1
if e_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif e_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif e_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
ei_c: int = 0
while ei_c < 3 and write_count < size - 1:
ec: int = 0
if e_sp == 3:
# nan
if ei_c == 0:
ec = 110
elif ei_c == 1:
ec = 97
else:
ec = 110
else:
# inf (e_sp==1 +inf or e_sp==2 -inf)
if ei_c == 0:
ec = 105
elif ei_c == 1:
ec = 110
else:
ec = 102
if e_upper and ec >= 97 and ec <= 122:
ec -= 32
ptr[0] = char(ec)
write_count += 1
ptr += _step
ei_c += 1
if left_align and width > e_total_len:
e_pad = width - e_total_len
while e_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
e_pad -= 1
fmt += 1
continue
if fv < 0.0:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
fv = 0.0 - fv
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
exp10: int = 0
if fv != 0.0:
# Upper-bound guard: inf makes the two loops below always true (inf/10==inf, inf*10==inf)
exp_guard: int = 0
while fv >= 10.0 and exp_guard < 400:
fv /= 10.0
exp10 += 1
exp_guard += 1
exp_guard = 0
while fv < 1.0 and exp_guard < 400:
fv *= 10.0
exp10 -= 1
exp_guard += 1
int_digit: int = int(fv)
if int_digit > 9: int_digit = 9
if int_digit < 0: int_digit = 0
frac_v: double = fv - double(int_digit)
p: int = 0
while p < precision:
frac_v *= 10.0
p += 1
frac_p: uint64 = uint64(frac_v + 0.5)
carry: uint64 = 1
for p in range(int(precision)):
carry *= 10
if frac_p >= carry and carry > 0:
frac_p = 0
int_digit += 1
if int_digit > 9:
int_digit = 1
exp10 += 1
e_total: int = 1 + (precision + 1 if precision > 0 else 0) + 4
if not left_align and not pad_zero and width > e_total:
pad_count = width - e_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if pad_zero and width > e_total:
pad_count = width - e_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
if write_count < size - 1:
ptr[0] = char(int_digit + 48)
write_count += 1
ptr += _step
if precision > 0:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
fi: int = 0
while fi < precision and fi < TEMP_BUF_SIZE - 1:
temp[fi] = char(frac_p % 10 + 48)
fi += 1
frac_p //= 10
while fi < precision and fi < TEMP_BUF_SIZE - 1:
temp[fi] = 48
fi += 1
while fi > 0 and write_count < size - 1:
fi -= 1
ptr[0] = temp[fi]
write_count += 1
ptr += _step
elif alt_form:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = char(101 if e_upper == 0 else 69)
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = char(45 if exp10 < 0 else 43)
write_count += 1
ptr += _step
exp_abs: uint64 = uint64(exp10) if exp10 >= 0 else uint64(0 - exp10)
ei: int = 0
if exp_abs == 0:
temp[0] = 48
temp[1] = 48
ei = 2
else:
while exp_abs > 0 and ei < TEMP_BUF_SIZE - 1:
temp[ei] = char(exp_abs % 10 + 48)
ei += 1
exp_abs //= 10
while ei < 2:
temp[ei] = 48
ei += 1
while ei > 0 and write_count < size - 1:
ei -= 1
ptr[0] = temp[ei]
write_count += 1
ptr += _step
if left_align and width > e_total:
pad_count = width - e_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 103 or *fmt == 71:
if precision < 0: precision = 6
if precision == 0: precision = 1
fv: double = arg(double)
g_upper: int = 1 if *fmt == 71 else 0
g_sp: int = _check_special_float(fv)
if g_sp != 0:
g_sgn_len: int = 0
if g_sp == 2:
g_sgn_len = 1
elif g_sp == 1 and show_sign:
g_sgn_len = 1
elif g_sp == 1 and space_sign:
g_sgn_len = 1
g_total_len: int = g_sgn_len + 3
if not left_align and width > g_total_len:
g_pad: int = width - g_total_len
while g_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
g_pad -= 1
if g_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif g_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif g_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
gi_c: int = 0
while gi_c < 3 and write_count < size - 1:
gc: int = 0
if g_sp == 3:
# nan
if gi_c == 0:
gc = 110
elif gi_c == 1:
gc = 97
else:
gc = 110
else:
# inf (g_sp==1 +inf or g_sp==2 -inf)
if gi_c == 0:
gc = 105
elif gi_c == 1:
gc = 110
else:
gc = 102
if g_upper and gc >= 97 and gc <= 122:
gc -= 32
ptr[0] = char(gc)
write_count += 1
ptr += _step
gi_c += 1
if left_align and width > g_total_len:
g_pad = width - g_total_len
while g_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
g_pad -= 1
fmt += 1
continue
if fv < 0.0:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
fv = 0.0 - fv
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
fv_orig: double = fv
exp10: int = 0
if fv != 0.0:
# Upper-bound guard: this loop is where it hangs (inf makes fv>=10.0 always true, inf/10==inf)
exp_guard: int = 0
while fv >= 10.0 and exp_guard < 400:
fv /= 10.0
exp10 += 1
exp_guard += 1
exp_guard = 0
while fv < 1.0 and exp_guard < 400:
fv *= 10.0
exp10 -= 1
exp_guard += 1
g_use_e: int = 0
if exp10 < -4 or exp10 >= precision:
g_use_e = 1
g_len: int = 0
if g_use_e:
int_digit: int = int(fv)
if int_digit > 9: int_digit = 9
if int_digit < 0: int_digit = 0
frac_v: double = fv - double(int_digit)
prec_e: int = precision - 1
p: int = 0
while p < prec_e:
frac_v *= 10.0
p += 1
frac_p: uint64 = uint64(frac_v + 0.5)
carry: uint64 = 1
for p in range(int(prec_e)):
carry *= 10
if frac_p >= carry and carry > 0:
frac_p = 0
int_digit += 1
if int_digit > 9:
int_digit = 1
exp10 += 1
temp[0] = char(int_digit + 48)
g_len = 1
if prec_e > 0:
temp[1] = 46
g_len = 2
# Store fraction digits in reverse order (ones place at g_len+prec_e-1) so temp is already forward-ordered.
# The original swap-reverse loop fails in TPV output (digits not reversed, e.g. 456->654); reverse storage matches %f's output and avoids the three-variable swap.
fi: int = 0
fp_inv: uint64 = frac_p
fp_idx: int = g_len + prec_e - 1
while fi < prec_e and fp_idx < TEMP_BUF_SIZE - 1:
temp[fp_idx] = char(fp_inv % 10 + 48)
fp_idx -= 1
fp_inv //= 10
fi += 1
g_len += prec_e
else:
prec_f: int = precision - 1 - exp10
if prec_f < 0: prec_f = 0
work: double = fv_orig
if work < 1.0:
temp[0] = 48
g_len = 1
else:
scale: double = 1.0
# Upper-bound guard: inf makes `work >= scale*10.0` always true; finite values need at most 308 iterations
scale_guard: int = 0
while work >= scale * 10.0 and scale_guard < 400:
scale *= 10.0
scale_guard += 1
while scale >= 1.0 and g_len < TEMP_BUF_SIZE - 1:
d: int = int(work / scale)
if d > 9: d = 9
temp[g_len] = char(d + 48)
g_len += 1
work = work - double(d) * scale
scale /= 10.0
if prec_f > 0 and g_len < TEMP_BUF_SIZE - 1:
temp[g_len] = 46
g_len += 1
frac_val: double = work
for p in range(int(prec_f)):
frac_val *= 10.0
frac_part: uint64 = uint64(frac_val + 0.5)
# Store decimal digits in reverse order (ones place goes to g_len prec_f-1), temp is directly in forward order.
# The original swap-reverse loop doesn't work in TPV compiled output (decimal digits aren't reversed, e.g., 456->654),
# Change to reverse storage, consistent with %f's reverse output, avoiding three-variable swapping.
fi = 0
fp_inv: uint64 = frac_part
fp_idx: int = g_len + prec_f - 1
while fi < prec_f and fp_idx < TEMP_BUF_SIZE - 1:
temp[fp_idx] = char(fp_inv % 10 + 48)
fp_idx -= 1
fp_inv //= 10
fi += 1
g_len += prec_f
if not alt_form and g_len > 0:
while g_len > 0:
if temp[g_len - 1] == 48:
g_len -= 1
else:
break
if g_len > 0 and temp[g_len - 1] == 46:
g_len -= 1
g_total: int = g_len
if g_use_e: g_total = g_len + 4
if not left_align and not pad_zero and width > g_total:
pad_count = width - g_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
if pad_zero and width > g_total:
pad_count = width - g_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
pad_count -= 1
gi: int = 0
while gi < g_len and write_count < size - 1:
ptr[0] = temp[gi]
write_count += 1
ptr += _step
gi += 1
if g_use_e:
if write_count < size - 1:
ptr[0] = char(101 if g_upper == 0 else 69)
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = char(45 if exp10 < 0 else 43)
write_count += 1
ptr += _step
exp_abs: uint64 = uint64(exp10) if exp10 >= 0 else uint64(0 - exp10)
ei: int = 0
if exp_abs == 0:
temp[0] = 48
temp[1] = 48
ei = 2
else:
while exp_abs > 0 and ei < TEMP_BUF_SIZE - 1:
temp[ei] = char(exp_abs % 10 + 48)
ei += 1
exp_abs //= 10
while ei < 2:
temp[ei] = 48
ei += 1
while ei > 0 and write_count < size - 1:
ei -= 1
ptr[0] = temp[ei]
write_count += 1
ptr += _step
if left_align and width > g_total:
pad_count = width - g_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
pad_count -= 1
elif *fmt == 97 or *fmt == 65:
a_upper: int = 1 if *fmt == 65 else 0
fv: double = arg(double)
a_sp: int = _check_special_float(fv)
if a_sp != 0:
a_sgn_len: int = 0
if a_sp == 2:
a_sgn_len = 1
elif a_sp == 1 and show_sign:
a_sgn_len = 1
elif a_sp == 1 and space_sign:
a_sgn_len = 1
a_total_len: int = a_sgn_len + 3
if not left_align and width > a_total_len:
a_pad: int = width - a_total_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
a_pad -= 1
if a_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif a_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif a_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
ai_c: int = 0
while ai_c < 3 and write_count < size - 1:
ac: int = 0
if a_sp == 3:
# nan
if ai_c == 0:
ac = 110
elif ai_c == 1:
ac = 97
else:
ac = 110
else:
# inf (a_sp==1 +inf or a_sp==2 -inf)
if ai_c == 0:
ac = 105
elif ai_c == 1:
ac = 110
else:
ac = 102
if a_upper and ac >= 97 and ac <= 122:
ac -= 32
ptr[0] = char(ac)
write_count += 1
ptr += _step
ai_c += 1
if left_align and width > a_total_len:
a_pad = width - a_total_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
a_pad -= 1
fmt += 1
continue
fbits: uint64 = 0
*&fbits = *&fv
a_neg: int = 1 if (fbits >> 63) != 0 else 0
a_exp: int = int((fbits >> 52) & 0x7FF)
a_frac: uint64 = fbits & 0x000FFFFFFFFFFFFF
a_leading: int = 0
a_binexp: int = 0
if a_exp == 0:
a_leading = 0
if a_frac == 0:
a_binexp = 0
else:
a_binexp = -1022
else:
a_leading = 1
a_binexp = a_exp - 1023
a_prec: int = precision
if a_prec < 0:
a_prec = 13
if a_prec > 50:
a_prec = 50
a_hi: int = 0
while a_hi < 13 and a_hi < a_prec:
a_digit: int = int((a_frac >> (48 - 4 * a_hi)) & 0xF)
if a_digit < 10:
temp[a_hi] = char(a_digit + 48)
else:
if a_upper:
temp[a_hi] = char(a_digit - 10 + 65)
else:
temp[a_hi] = char(a_digit - 10 + 97)
a_hi += 1
while a_hi < a_prec:
temp[a_hi] = 48
a_hi += 1
a_hd_count: int = a_prec
if precision < 0:
while a_hd_count > 0 and temp[a_hd_count - 1] == 48:
a_hd_count -= 1
a_has_dot: int = 0
if a_hd_count > 0:
a_has_dot = 1
elif alt_form:
a_has_dot = 1
a_eb: int = a_binexp
a_esign: int = 0
if a_binexp < 0:
a_esign = 1
a_eb = -a_binexp
a_ei: int = 0
if a_eb == 0:
temp[60] = 48
a_ei = 1
else:
while a_eb > 0 and a_ei < 7:
temp[60 + a_ei] = char(a_eb % 10 + 48)
a_ei += 1
a_eb //= 10
a_ecount: int = a_ei
a_sign_len: int = 0
if a_neg:
a_sign_len = 1
elif show_sign:
a_sign_len = 1
elif space_sign:
a_sign_len = 1
a_content_len: int = a_sign_len + 2 + 1 + a_has_dot + a_hd_count + 1 + 1 + a_ecount
if not left_align and not pad_zero and width > a_content_len:
a_pad = width - a_content_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
a_pad -= 1
if a_neg:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
if pad_zero and width > a_content_len:
a_pad = width - a_content_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
a_pad -= 1
if write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
if write_count < size - 1:
if a_upper:
ptr[0] = 88
else:
ptr[0] = 120
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = char(a_leading + 48)
write_count += 1
ptr += _step
if a_has_dot:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
a_hj: int = 0
while a_hj < a_hd_count and write_count < size - 1:
ptr[0] = temp[a_hj]
write_count += 1
ptr += _step
a_hj += 1
if write_count < size - 1:
if a_upper:
ptr[0] = 80
else:
ptr[0] = 112
write_count += 1
ptr += _step
if write_count < size - 1:
if a_esign:
ptr[0] = 45
else:
ptr[0] = 43
write_count += 1
ptr += _step
a_ek: int = a_ecount
while a_ek > 0 and write_count < size - 1:
a_ek -= 1
ptr[0] = temp[60 + a_ek]
write_count += 1
ptr += _step
if left_align and width > a_content_len:
a_pad = width - a_content_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
a_pad -= 1
elif *fmt == 110:
if is_long_long or is_long:
np: int64* = arg(int64*)
if np != None:
np[0] = int64(write_count)
elif is_short:
sp: short* = arg(short*)
if sp != None:
sp[0] = short(write_count)
elif is_char:
cp: str = arg(str)
if cp != None:
cp[0] = char(write_count)
else:
ip: int* = arg(int*)
if ip != None:
ip[0] = write_count
elif *fmt == 37:
if write_count < size - 1:
ptr[0] = 37
write_count += 1
ptr += _step
else:
if write_count < size - 1:
ptr[0] = *fmt
write_count += 1
ptr += _step
fmt += 1
ptr[0] = 0
return write_count