1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
import "all.hff";
extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) void {
defmacro p(x) [ proc(x, parg) ]
defmacro ps(s) [
for let $i = 0; (s)[$i] != 0; ++$i {
p(s[$i]);
}
]
let buf [100]u8 = {};
for let c u8 = *fmt; c != 0; c = *++fmt {
assert(c != 0, "?");
if c != '%' {
p(c);
if fmt[1] == 0 { break; }
continue;
}
let quote = #f;
#'fmt do {
switch (c = *++fmt) {
case 'i';
sprintf(buf, "%d", ap->arg(int));
ps(buf);
case 'q';
quote = #t;
continue #'fmt;
case 'c';
let ch u32 = ap->arg(int);
if quote {
extern fn isprint(int) int;
p('\'');
for ch = bswap32(ch); ch != 0; ch >>= 8 {
if ch & 0xFF != 0 {
if isprint(ch) != 0 { p(ch); }
else {
p('\\');
p('0' + (ch % 8));
p('0' + ((ch / 8) % 8));
p('0' + ((ch / 8 / 8) % 8));
}
}
}
p('\'');
} else {
if ch == 0 { p(0); }
else {
for ch = bswap32(ch); ch != 0; ch >>= 8 {
if ch & 0xFF != 0 {
p(ch & 0xFF);
}
}
}
}
case 's';
let s = ap->arg(*const u8);
if quote {
extern fn isprint(int) int;
p('\"');
for let c u8 #?; (c = *s++) != 0; {
if isprint(c) != 0 {
p(c);
} else {
p('\\');
p('0' + (c % 8));
p('0' + ((c / 8) % 8));
p('0' + ((c / 8 / 8) % 8));
}
}
p('\"');
} else {
ps(s);
}
case else
// assert(#f, "bad fmt '%c' @ %d", c, i);
}
} while #f;
}
}
extern fn vefmt(fmt *const u8, ap va_list) void {
fn epri(c u8, *void) void {
fputc(c, stderr);
}
vpfmt(&epri, #null, fmt, ap);
}
extern fn efmt(fmt *const u8, ...) void {
let ap va_list #?;
ap->start(fmt);
vefmt(fmt, ap);
ap->end();
}
|