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(); }