ww: import toolchain — C bootstrap + ww-side self-host (phases 0-10)
C bootstrap (phases 0-9):
cmd/wwc, cmd/6c, cmd/6a, cmd/6l, cmd/ww, rt, lib/*.
ww-side self-host (phase 10):
selfhost/cmd/wwc — ww-cgen frontend; bootstrap fixed point.
selfhost/cmd/6a — assembler; byte-identical to C 6a (test 991).
selfhost/cmd/6l — linker w/ archive (.a) support; byte-identical
to C 6l (test 992).
selfhost/cmd/ww — driver (build/run/version); byte-identical to
C ww (test 993).
make test: 15/15. make bootstrap: ww2.s == ww3.s, ww2.o == ww3.o,
ww2 == ww3 byte-identical, with the full ww-tooled chain.
This commit is contained in:
119
lib/strconv/strconv.ww
Normal file
119
lib/strconv/strconv.ww
Normal file
@@ -0,0 +1,119 @@
|
||||
// strconv — number↔string conversions. Decimal i64 to/from a fixed
|
||||
// buffer. Two error idioms ship side by side:
|
||||
// - Plan 9 style (atoi64): tuple `(value, ok)`. Pre-dates the
|
||||
// tagged-union work; kept for callers that already use it.
|
||||
// - Hare style (parse64/parseu64): `(value | str)`. The error
|
||||
// variant carries a short, allocation-free message describing
|
||||
// why the parse failed. Prefer this for new code.
|
||||
|
||||
// u64toa — write `v` in decimal into `buf` and return the byte count.
|
||||
// Unsigned-only so callers don't have to think about wraparound when
|
||||
// printing a u64 that happens to have the high bit set.
|
||||
export fn u64toa(buf: []u8, v: u64) i32 = {
|
||||
let tmp: [32]u8;
|
||||
let i: i32 = 0;
|
||||
let n: u64 = v;
|
||||
for (n > 0u64) {
|
||||
tmp[i] = ((n % 10u64) + 48u64): u8;
|
||||
n = n / 10u64;
|
||||
i += 1;
|
||||
};
|
||||
if (i == 0) {
|
||||
tmp[0] = 48u8;
|
||||
i = 1;
|
||||
};
|
||||
let out: i32 = 0;
|
||||
for (i > 0) {
|
||||
i -= 1;
|
||||
buf[out] = tmp[i];
|
||||
out += 1;
|
||||
};
|
||||
return out;
|
||||
};
|
||||
|
||||
export fn i64toa(buf: []u8, v: i64) i32 = {
|
||||
let neg: bool = false;
|
||||
let n: i64 = v;
|
||||
if (n < 0) {
|
||||
neg = true;
|
||||
n = -n;
|
||||
};
|
||||
let tmp: [32]u8;
|
||||
let i: i32 = 0;
|
||||
for (n > 0) {
|
||||
tmp[i] = ((n % 10) + 48): u8;
|
||||
n = n / 10;
|
||||
i += 1;
|
||||
};
|
||||
if (i == 0) {
|
||||
tmp[0] = 48u8;
|
||||
i = 1;
|
||||
};
|
||||
let out: i32 = 0;
|
||||
if (neg) {
|
||||
buf[out] = 45u8; // '-'
|
||||
out += 1;
|
||||
};
|
||||
for (i > 0) {
|
||||
i -= 1;
|
||||
buf[out] = tmp[i];
|
||||
out += 1;
|
||||
};
|
||||
return out;
|
||||
};
|
||||
|
||||
export fn atoi64(s: str) (i64, bool) = {
|
||||
let v: i64 = 0;
|
||||
let i: i32 = 0;
|
||||
let neg: bool = false;
|
||||
if (s.len > 0) {
|
||||
if (s[0] == 45u8) { neg = true; i = 1; };
|
||||
};
|
||||
if (i >= s.len) { return 0, false; };
|
||||
for (i < s.len) {
|
||||
let c: u8 = s[i];
|
||||
if (c < 48u8) { return 0, false; };
|
||||
if (c > 57u8) { return 0, false; };
|
||||
v = v * 10 + ((c: i64) - 48);
|
||||
i += 1;
|
||||
};
|
||||
if (neg) { v = -v; };
|
||||
return v, true;
|
||||
};
|
||||
|
||||
// parse64 — Hare-style fallible signed decimal parser. The value
|
||||
// variant is i64; the error variant is a short str describing the
|
||||
// reason. No locale, no whitespace, no underscores: a leading '-' is
|
||||
// the only non-digit accepted, and only at position 0.
|
||||
export fn parse64(s: str) (i64 | str) = {
|
||||
if (s.len == 0) { return "parse: empty"; };
|
||||
let i: i32 = 0;
|
||||
let neg: bool = false;
|
||||
if (s[0] == 45u8) { neg = true; i = 1; };
|
||||
if (i >= s.len) { return "parse: lone sign"; };
|
||||
let v: i64 = 0;
|
||||
for (i < s.len) {
|
||||
let c: u8 = s[i];
|
||||
if (c < 48u8) { return "parse: invalid digit"; };
|
||||
if (c > 57u8) { return "parse: invalid digit"; };
|
||||
v = v * 10 + ((c: i64) - 48);
|
||||
i += 1;
|
||||
};
|
||||
if (neg) { v = -v; };
|
||||
return v;
|
||||
};
|
||||
|
||||
// parseu64 — fallible unsigned decimal parser. No leading sign.
|
||||
export fn parseu64(s: str) (u64 | str) = {
|
||||
if (s.len == 0) { return "parse: empty"; };
|
||||
let v: u64 = 0u64;
|
||||
let i: i32 = 0;
|
||||
for (i < s.len) {
|
||||
let c: u8 = s[i];
|
||||
if (c < 48u8) { return "parse: invalid digit"; };
|
||||
if (c > 57u8) { return "parse: invalid digit"; };
|
||||
v = v * 10u64 + ((c: u64) - 48u64);
|
||||
i += 1;
|
||||
};
|
||||
return v;
|
||||
};
|
||||
Reference in New Issue
Block a user