aboutsummaryrefslogtreecommitdiff
path: root/src/fmt.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-12 16:43:06 +0200
committerlemon <lsof@mailbox.org>2022-08-12 16:43:06 +0200
commit1eb17cda6780476b166b55d0fedc3ad355969e87 (patch)
treeccb4ffa74cc37f24e93d4325ccf395d3fe73529f /src/fmt.cff
parentf14aee6184568bae34f8d8d8f9140fa760099fa5 (diff)
selfhosted lexer
Diffstat (limited to 'src/fmt.cff')
-rw-r--r--src/fmt.cff113
1 files changed, 82 insertions, 31 deletions
diff --git a/src/fmt.cff b/src/fmt.cff
index 885ea50..ecf7d74 100644
--- a/src/fmt.cff
+++ b/src/fmt.cff
@@ -3,41 +3,83 @@ 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]);
+ for let $s *const u8 = (s); *$s != 0; ++$s {
+ p(*$s);
}
]
- let buf [100]u8 = {};
+
+ defmacro pch(ch) [ {
+ extern fn isprint(int) int;
+ if isprint(ch) != 0 {
+ p(ch);
+ } else {
+ p('\\');
+ p('0' + (ch % 8));
+ p('0' + ((ch / 8) % 8));
+ p('0' + ((ch / 8 / 8) % 8));
+ }
+ } ]
+
+ static buf [100]u8 = {};
+
+ fn pritok(proc typeof(proc), parg *void, quote bool, tok *const Tok) void {
+ switch tok.t {
+ case :int;
+ sprintf(buf, "%lld", tok.u.int);
+ ps(buf);
+ case :str;
+ pfmt(proc, parg, "%S", tok.u.str);
+ case :ident;
+ if quote { p('`'); }
+ ps(tok.u.ident);
+ if quote { p('\''); }
+ case else
+ if tok.t >= 0 and tok.t < NUM_KEYWORDS {
+ if quote { p('`'); }
+ ps(tok.u.ident);
+ if quote { p('\''); }
+ } else if tok.t > 0 {
+ if quote { p('`'); }
+ let t = bswap32(tok.t);
+ let i = 0;
+ while t != 0 {
+ if t & 0xFF != 0 {
+ p(t);
+ }
+ t >>= 8;
+ }
+ buf[i] = '\0';
+ if quote { p('\''); }
+ }
+ }
+ }
+
for let c u8 = *fmt; c != 0; c = *++fmt {
assert(c != 0, "?");
if c != '%' {
p(c);
if fmt[1] == 0 { break; }
- continue;
+ continue;
}
let quote = #f;
- #'fmt do {
+ for ;; {
switch (c = *++fmt) {
- case 'i';
- sprintf(buf, "%d", ap->arg(int));
- ps(buf);
case 'q';
quote = #t;
- continue #'fmt;
+ continue;
+ case 'i', 'd';
+ sprintf(buf, "%d", ap->arg(int));
+ ps(buf);
+ case 'p';
+ sprintf(buf, "%p", ap->arg(*void));
+ ps(buf);
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));
- }
+ pch(ch);
}
}
p('\'');
@@ -57,38 +99,47 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list)
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));
- }
+ pch(c);
}
p('\"');
} else {
ps(s);
}
+ case 'S';
+ let str = ap->arg([#]const u8);
+ p('"');
+ foreach(c, i, str,
+ pch(c);
+ )
+ p('"');
+ case 'T';
+ let tok = ap->arg(Tok);
+ pritok(proc, parg, quote, &tok);
case else
- // assert(#f, "bad fmt '%c' @ %d", c, i);
+ assert(#f, "bad fmt '%c'", c);
}
- } while #f;
+ break;
+ }
}
}
+extern fn pfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ...) void {
+ let ap va_list #?;
+ ap->start(fmt);
+ vpfmt(proc, parg, fmt, ap);
+ ap->end();
+}
+
extern fn vefmt(fmt *const u8, ap va_list) void {
- fn epri(c u8, *void) void {
+ fn eputc(c u8, *void) void {
fputc(c, stderr);
}
-
- vpfmt(&epri, #null, fmt, ap);
+ vpfmt(&eputc, #null, fmt, ap);
}
extern fn efmt(fmt *const u8, ...) void {
let ap va_list #?;
ap->start(fmt);
-
vefmt(fmt, ap);
ap->end();
}