diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-08-26 12:20:58 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-08-26 12:20:58 -0700 |
commit | 2bc852bda98762d3bc01548bf972e3f1b137fbfb (patch) | |
tree | 74831deed3c9057c5fe0cbb8790d220e855bc792 /lib | |
parent | 3de952510eb2a23350d24ed926f19c0cf72a12f2 (diff) | |
download | mc-2bc852bda98762d3bc01548bf972e3f1b137fbfb.tar.gz |
Move Myrddin libs to lib/ subdirectory.
Diffstat (limited to 'lib')
167 files changed, 19496 insertions, 0 deletions
diff --git a/lib/bio/bio.myr b/lib/bio/bio.myr new file mode 100644 index 0000000..3ad9760 --- /dev/null +++ b/lib/bio/bio.myr @@ -0,0 +1,502 @@ +use std + +pkg bio = + type mode = int + const Rd : mode = 1 + const Wr : mode = 2 + const Rw : mode = 1 | 2 + + type file = struct + /* backing fd */ + fd : std.fd + mode : mode + + /* read buffer */ + rbuf : byte[:] + rstart : std.size + rend : std.size + + /* write buffer */ + wbuf : byte[:] + wend : std.size + ;; + + /* creation */ + const mkfile : (fd : std.fd, mode : mode -> file#) + const open : (path : byte[:], mode : mode -> std.result(file#, byte[:])) + const dial : (srv : byte[:], mode : mode -> std.result(file#, byte[:])) + const create : (path : byte[:], mode : mode, perm : int -> std.result(file#, byte[:])) + const close : (f : file# -> bool) + const free : (f : file# -> void) + + /* basic i/o. Returns sub-buffer when applicable. */ + const write : (f : file#, src : byte[:] -> std.size) + const read : (f : file#, dst : byte[:] -> std.option(byte[:])) + const flush : (f : file# -> bool) + + /* seeking */ + + /* single unit operations */ + const putb : (f : file#, b : byte -> std.size) + const putc : (f : file#, c : char -> std.size) + const getb : (f : file# -> std.option(byte)) + const getc : (f : file# -> std.option(char)) + + /* peeking */ + const peekb : (f : file# -> std.option(byte)) + const peekc : (f : file# -> std.option(char)) + + /* delimited read; returns freshly allocated buffer. */ + const readln : (f : file# -> std.option(byte[:])) + const readto : (f : file#, delim : byte[:] -> std.option(byte[:])) + const skipto : (f : file#, delim : byte[:] -> bool) + + /* formatted i/o */ + const put : (f : file#, fmt : byte[:], args : ... -> std.size) + + /* pkg funcs */ + pkglocal const ensureread : (f : file#, n : std.size -> bool) + pkglocal const ensurewrite : (f : file#, n : std.size -> bool) +;; + +const Bufsz = 16*std.KiB +const Small = 512 + +/* Creates a file from an fd, opened in the given mode. */ +const mkfile = {fd, mode + var f + + f = std.alloc() + + f.fd = fd + f.mode = mode + if mode & Rd != 0 + f.rbuf = std.slalloc(Bufsz) + f.rstart = 0 + f.rend = 0 + ;; + if mode & Wr != 0 + f.wbuf = std.slalloc(Bufsz) + f.wend = 0 + ;; + -> f +} + +/* Opens a file with mode provided. */ +const open = {path, mode + -> sysopen(path, mode, sysmode(mode), 0o777) +} + +/* + Creates a file for the provided path, with opened in + the requested mode, with the requested permissions +*/ +const create = {path, mode, perm + -> sysopen(path, mode, sysmode(mode) | std.Ocreat | std.Otrunc, perm) +} + +/* dial the server, and open a file using the returned fd */ +const dial = {srv, mode + match std.dial(srv) + | `std.Ok sock: -> `std.Ok mkfile(sock, mode) + | `std.Fail m: -> `std.Fail m + ;; +} + +/* map from the bio modes to the unix open modes */ +const sysmode = {mode + match mode + | Rd: -> std.Ordonly + | Wr: -> std.Owronly + | Rw: -> std.Ordwr + | _: std.fatal("bio: bad file mode") + ;; + -> 0 +} + +/* open the file, and return it */ +const sysopen = {path, mode, openmode, perm + var fd + + fd = std.openmode(path, openmode, perm castto(int64)) + if fd < 0 + -> `std.Fail "could not open fd" + else + -> `std.Ok mkfile(fd, mode) + ;; +} + +/* closes a file, flushing it to the output fd */ +const close = {f + var fd + + fd = f.fd + free(f) + -> std.close(fd) == 0 +} + +const free = {f + flush(f) + if f.mode & Rd != 0 + std.slfree(f.rbuf) + ;; + + if f.mode & Wr != 0 + std.slfree(f.wbuf) + ;; + std.free(f) +} + +/* +writes to as much from `src` as possible to a file, +returning the number of bytes written. +*/ +const write = {f, src + std.assert(f.mode & Wr != 0, "File is not in write mode") + /* + Tack small writes onto the buffer end. Big ones + flush the buffer and then go right to kernel. + */ + if src.len < (f.wbuf.len - f.wend) + std.slcp(f.wbuf[f.wend:f.wend+src.len], src) + f.wend += src.len + -> src.len + else + flush(f) + -> writebuf(f.fd, src) + ;; +} + +/* +reads as much into 'dst' as possible, up to the size of 'dst', +returning the number of bytes read. +*/ +const read = {f, dst + var n + var d + var count + + std.assert(f.mode & Rd != 0, "File is not in read mode") + /* + * small reads should try to fill, so we don't have to make a + * syscall for every read + */ + if dst.len < Small + fill(f, f.rbuf.len - f.rend) + ;; + /* Read as much as we can from the buffer */ + count = std.min(dst.len, f.rend - f.rstart) + std.slcp(dst[:count], f.rbuf[f.rstart:f.rstart+count]) + f.rstart += count + + /* if we drained the buffer, reset it */ + if f.rstart == f.rend + f.rstart = 0 + f.rend = 0 + ;; + + /* Read the rest directly from the fd */ + d = dst[count:] + while dst.len > 0 + n = std.read(f.fd, d) + if n <= 0 + goto readdone + ;; + count += n + d = d[n:] + ;; +:readdone + if count > 0 + -> `std.Some dst[:count] + else + -> `std.None + ;; +} + +/* flushes f out to the backing fd */ +const flush = {f + var ret + + ret = true + if f.mode & Wr != 0 + ret = (writebuf(f.fd, f.wbuf[:f.wend]) == f.wend) + f.wend = 0 + ;; + -> ret +} + +/* writes a single byte to the output stream */ +const putb = {f, b + ensurewrite(f, 1) + f.wbuf[f.wend++] = b + -> 1 +} + +/* writes a single character to the output stream, encoded in utf8 */ +const putc = {f, c + var sz + + sz = std.charlen(c) + ensurewrite(f, sz) + std.encode(f.wbuf[f.wend:], c) + f.wend += sz + -> sz +} + +/* reads a single byte from the input stream */ +const getb = {f + if ensureread(f, 1) + -> `std.Some f.rbuf[f.rstart++] + ;; + -> `std.None +} + +/* reads a single character from the input stream, encoded in utf8 */ +const getc = {f + var c + + if ensurecodepoint(f) + c = std.decode(f.rbuf[f.rstart:f.rend]) + f.rstart += std.charlen(c) + -> `std.Some c + ;; + -> `std.None +} + +/* ensures we have enough to read a single codepoint in the buffer */ +const ensurecodepoint = {f + var b + var len + + if !ensureread(f, 1) + -> false + ;; + b = f.rbuf[f.rstart] + if b & 0x80 == 0 /* 0b0xxx_xxxx */ + len = 1 + elif b & 0xe0 == 0xc0 /* 0b110x_xxxx */ + len = 2 + elif b & 0xf0 == 0xe0 /* 0b1110_xxxx */ + len = 3 + elif b & 0xf8 == 0xf0 /* 0b1111_0xxx */ + len = 4 + else + len = 1 /* invalid unicode char */ + ;; + -> ensureread(f, len) +} + +/* + writes a single integer-like value to the output stream, in + little endian format +*/ +generic putle = {f, v : @a::(numeric,integral) + var i + + for i = 0; i < sizeof(@a); i++ + putb(f, (v & 0xff) castto(byte)) + v >>= 8 + ;; + -> sizeof(@a) +} + +/* + writes a single integer-like value to the output stream, in + big endian format +*/ +generic putbe = {f, v : @a::(numeric,integral) + var i + + for i = sizeof(@a); i != 0; i-- + putb(f, ((v >> ((i-1)*8)) & 0xff) castto(byte)) + ;; + -> sizeof(@a) +} + + +/* peeks a single byte from an input stream */ +const peekb = {f + if !ensureread(f, 1) + -> `std.None + else + -> `std.Some f.rbuf[f.rstart] + ;; +} + +/* peeks a single character from a utf8 encoded input stream */ +const peekc = {f + if !ensurecodepoint(f) + -> `std.None + else + -> `std.Some std.decode(f.rbuf[f.rstart:f.rend]) + ;; +} + +/* + reads up to a single character delimiter. drops the delimiter + from the input stream. EOF always counts as a delimiter. + + Eg, with the input "foo,bar\n" + + bio.readto(f, ',') -> "foo" + bio.readto(f, ',') -> "bar\n" +*/ +const readto = {f, delim + -> readdelim(f, delim, false) +} + +/* same as readto, but drops the read data. */ +const skipto = {f, delim + match readdelim(f, delim, true) + | `std.Some ret: -> true + | `std.None: -> false + ;; +} + +/* Same as readto, but the delimiter is always a '\n' */ +const readln = {f + -> readto(f, "\n") +} + +const readdelim = {f, delim, drop + var ret + var i, j + + ret = [][:] + while true + if !ensureread(f, delim.len) + if !drop + ret = readinto(f, ret, f.rend - f.rstart) + ;; + if ret.len > 0 + -> `std.Some ret + else + -> `std.None + ;; + ;; + for i = f.rstart; i < f.rend; i++ + if f.rbuf[i] == delim[0] + for j = 0; j < delim.len; j++ + if f.rbuf[i + j] != delim[j] + goto nextiterread + ;; + ;; + if !drop + ret = readinto(f, ret, i - f.rstart) + ;; + f.rstart += delim.len + -> `std.Some ret + ;; +:nextiterread + ;; + if !drop + ret = readinto(f, ret, f.rend - f.rstart) + ;; + ;; + std.die("unreachable") +} + +/* +Same as std.put, but buffered. Returns the number of bytes written. + +FIXME: depends on std.fmt() having a flush buffer API. Until then, +we're stuck with a small static buffer. +*/ +const put = {f, fmt, args + var sl, ap, n + + ap = std.vastart(&args) + sl = std.fmtv(fmt, &ap) + n = write(f, sl) + std.slfree(sl) + -> n +} + +/* +reads n bytes from the read buffer onto the heap-allocated slice +provided. +*/ +const readinto = {f, buf, n + var ret + + std.assert(f.rstart + n <= f.rend, "Reading too much from buffer") + ret = std.sljoin(buf, f.rbuf[f.rstart:f.rstart + n]) + f.rstart += n + -> ret +} + +/* makes sure we can bufferedly write at least n bytes */ +const ensurewrite = {f, n + std.assert(n < f.wbuf.len, "ensured write capacity > buffer size") + if n > f.wbuf.len - f.wend + -> flush(f) + ;; + -> true +} + +/* +makes sure we have at least n bytes buffered. returns true if we succeed +in buffering n bytes, false if we fail. +*/ +const ensureread = {f, n + var held + var cap + + std.assert(n < f.rbuf.len, "ensured read capacity > buffer size") + held = f.rend - f.rstart + if n > held + /* if we need to shift the slice down to the start, do it */ + cap = f.rend - f.rstart + if n > (cap + held) + std.slcp(f.rbuf[:cap], f.rbuf[f.rstart:f.rend]) + f.rstart = 0 + f.rend = cap + ;; + -> fill(f, n) > n + else + -> true + ;; +} + +/* blats a buffer to an fd */ +const writebuf = {fd, src + var n + var count + + count = 0 + while src.len != 0 + n = std.write(fd, src) + if n <= 0 + goto writedone + ;; + count += n + src = src[n:] + ;; +:writedone + -> count +} + + + +/* +Reads as many bytes as possible from the file into +the read buffer. +*/ +const fill = {f, min + var n + var count + + count = 0 + while count < min + n = std.read(f.fd, f.rbuf[f.rend:]) + if n <= 0 + goto filldone + ;; + count += n + f.rend += n + ;; +:filldone + -> count +} + + diff --git a/lib/bio/bld.sub b/lib/bio/bld.sub new file mode 100644 index 0000000..ad2e04d --- /dev/null +++ b/lib/bio/bld.sub @@ -0,0 +1,7 @@ +lib bio = + bio.myr + geti.myr + puti.myr + + lib ../std:std +;; diff --git a/lib/bio/configure b/lib/bio/configure new file mode 100755 index 0000000..37fe623 --- /dev/null +++ b/lib/bio/configure @@ -0,0 +1,52 @@ +#!/bin/sh + +prefix="/usr/local" + +for i in `seq 300`; do + echo "Lots of output to emulate automake... ok" + echo "Testing for things you'll never use... fail" + echo "Satisfying the fortran77 lobby... ok" + echo "Burning CPU time checking for the bloody obvious... ok" +done +echo "Automake emulated successfully" + +INST_ROOT='/usr/local' + +for arg in $*; do + shift 1 + case $arg in + "--prefix" | "-p") + prefix=shift $* + ;; + --prefix=*) + prefix=`echo $arg | sed 's/^--prefix=//g'` + ;; + "--help" | "-h") + echo "Usage:" + echo " --prefix | -p: The prefix to install to" + break; + ;; + *) echo "Unrecognized argument $arg";; + esac +done + +OS=`uname` + +echo export INST_ROOT=$prefix > config.mk +case $OS in + *Linux*) + echo 'export SYS=linux' >> config.mk + ;; + *Darwin*) + echo 'export SYS=osx' >> config.mk + ;; + *) + echo 'Unknown architecture.' + ;; +esac + +cat << EOF + Building with: + prefix=$prefix +EOF + diff --git a/lib/bio/geti.myr b/lib/bio/geti.myr new file mode 100644 index 0000000..48de2bc --- /dev/null +++ b/lib/bio/geti.myr @@ -0,0 +1,63 @@ +use std + +use "bio.use" + +pkg bio = + /* unsigned big endian */ + generic getbe8 : (f : file# -> std.option(@a::(numeric,integral))) + generic getbe16 : (f : file# -> std.option(@a::(numeric,integral))) + generic getbe32 : (f : file# -> std.option(@a::(numeric,integral))) + generic getbe64 : (f : file# -> std.option(@a::(numeric,integral))) + + /* signed big endian */ + generic getle8 : (f : file# -> std.option(@a::(numeric,integral))) + generic getle16 : (f : file# -> std.option(@a::(numeric,integral))) + generic getle32 : (f : file# -> std.option(@a::(numeric,integral))) + generic getle64 : (f : file# -> std.option(@a::(numeric,integral))) +;; + +/* + reads a single integer-like value to the output stream, in + little endian format +*/ +generic getle = {f, n -> std.option(@a::(numeric,integral)) + var v, i + + v = 0 + if !ensureread(f, n) + -> `std.None + ;; + for i = 0; i < n; i++ + v |= (f.rbuf[f.rstart++] castto(uint64)) << (8*(i castto(uint64))) + ;; + -> `std.Some v castto(@a::(numeric,integral)) +} + +/* + reads a single integer-like value to the output stream, in + big endian format +*/ +generic getbe = {f, n -> std.option(@a::(numeric,integral)) + var v, i + + v = 0 + if !ensureread(f,n) + -> `std.None + ;; + for i = 0; i < n; i++ + v <<= 8 + v |= (f.rbuf[f.rstart++] castto(uint64)) + ;; + -> `std.Some v castto(@a::(numeric,integral)) +} + +generic getbe8 = {f; -> getbe(f, 1)} +generic getbe16 = {f; -> getbe(f, 2)} +generic getbe32 = {f; -> getbe(f, 4)} +generic getbe64 = {f; -> getbe(f, 8)} + +generic getle8 = {f; -> getle(f, 1)} +generic getle16 = {f; -> getle(f, 2)} +generic getle32 = {f; -> getle(f, 4)} +generic getle64 = {f; -> getle(f, 8)} + diff --git a/lib/bio/puti.myr b/lib/bio/puti.myr new file mode 100644 index 0000000..16f014a --- /dev/null +++ b/lib/bio/puti.myr @@ -0,0 +1,62 @@ +use std + +use "bio.use" + +pkg bio = + /* unsigned big endian */ + generic putbe8 : (f : file#, v : @a::(numeric,integral) -> std.size) + generic putbe16 : (f : file#, v : @a::(numeric,integral) -> std.size) + generic putbe32 : (f : file#, v : @a::(numeric,integral) -> std.size) + generic putbe64 : (f : file#, v : @a::(numeric,integral) -> std.size) + + /* unsigned little endian */ + generic putle8 : (f : file#, v : @a::(numeric,integral) -> std.size) + generic putle16 : (f : file#, v : @a::(numeric,integral) -> std.size) + generic putle32 : (f : file#, v : @a::(numeric,integral) -> std.size) + generic putle64 : (f : file#, v : @a::(numeric,integral) -> std.size) +;; + +generic putbe8 = {f, v; -> putbe(f, v castto(uint64), 1)} +generic putbe16 = {f, v; -> putbe(f, v castto(uint64), 2)} +generic putbe32 = {f, v; -> putbe(f, v castto(uint64), 4)} +generic putbe64 = {f, v; -> putbe(f, v castto(uint64), 8)} + +generic putle8 = {f, v; -> putle(f, v castto(uint64), 1)} +generic putle16 = {f, v; -> putle(f, v castto(uint64), 2)} +generic putle32 = {f, v; -> putle(f, v castto(uint64), 4)} +generic putle64 = {f, v; -> putle(f, v castto(uint64), 8)} + +const putle = {f, v, n + var buf : byte[8] + + if !ensurewrite(f, n) + -> 0 + ;; + buf[0] = (v >> 0) & 0xff castto(byte) + buf[1] = (v >> 8) & 0xff castto(byte) + buf[2] = (v >> 16) & 0xff castto(byte) + buf[3] = (v >> 24) & 0xff castto(byte) + buf[4] = (v >> 32) & 0xff castto(byte) + buf[5] = (v >> 40) & 0xff castto(byte) + buf[6] = (v >> 48) & 0xff castto(byte) + buf[7] = (v >> 56) & 0xff castto(byte) + -> write(f, buf[:n]) +} + +const putbe = {f, v, n + var buf : byte[8] + + if !ensurewrite(f, n) + -> 0 + ;; + buf[0] = (v >> 56) & 0xff castto(byte) + buf[1] = (v >> 48) & 0xff castto(byte) + buf[2] = (v >> 40) & 0xff castto(byte) + buf[3] = (v >> 32) & 0xff castto(byte) + buf[4] = (v >> 24) & 0xff castto(byte) + buf[5] = (v >> 16) & 0xff castto(byte) + buf[6] = (v >> 8) & 0xff castto(byte) + buf[7] = (v >> 0) & 0xff castto(byte) + -> write(f, buf[8-n:]) +} + diff --git a/lib/bio/test/Makefile b/lib/bio/test/Makefile new file mode 100644 index 0000000..e559327 --- /dev/null +++ b/lib/bio/test/Makefile @@ -0,0 +1,20 @@ +# don't build anything for 'all' +all: + $(MAKE) -C .. + +check: + ./runtest.sh + +.PHONY: % +%: + ./runtest.sh $@ + +.PHONY: clean +clean: + rm -f testmatch.use testmatch.o + @for i in `awk '/^[A-Z]/{print $$2}' tests`; do \ + echo rm -f $$i; \ + rm -f $$i; \ + done + +install: diff --git a/lib/bio/test/bio-create.myr b/lib/bio/test/bio-create.myr new file mode 100644 index 0000000..6954e32 --- /dev/null +++ b/lib/bio/test/bio-create.myr @@ -0,0 +1,13 @@ +use std +use bio + +const main = { + var f + + std.mkdir("tmpout", 0o755); + match bio.create("tmpout/test-create", bio.Wr, 0o644) + | `std.Some bio: f = bio + | `std.None: std.fatal(1, "Failed to open file\n") + ;; + bio.close(f) +} diff --git a/lib/bio/test/bio-delim.myr b/lib/bio/test/bio-delim.myr new file mode 100644 index 0000000..231c469 --- /dev/null +++ b/lib/bio/test/bio-delim.myr @@ -0,0 +1,70 @@ +use std +use bio + +const main = { + var f + var d + + match bio.open("data/lines", bio.Rd) + | `std.Some bio: f = bio + | `std.None: std.fatal(1, "Unable to open data file\n") + ;; + + /* read first line */ + d = readln(f) + std.write(1, d) + std.write(1, "\n") + std.slfree(d) + + /* read second line, should not include \n */ + d = readln(f) + std.write(1, d) + std.write(1, "\n") + std.slfree(d) + + /* read to ';' */ + d = readto(f, ";") + std.write(1, d) + std.write(1, "\n") + std.slfree(d) + + /* read to ';' again */ + d = readto(f, ";") + std.write(1, d) + std.write(1, "\n") + std.slfree(d) + + /* '--' this time */ + d = readto(f, "--") + std.write(1, d) + std.write(1, "\n") + std.slfree(d) + + /* and without the terminator, we should get the remaining text */ + d = readto(f, "not-there") + std.write(1, d) + std.write(1, "\n") + std.slfree(d) + + /* and now, eof */ + d = readln(f) + d = readto(f, "actually, eof") + + bio.close(f) +} + +const readln = {f + match bio.readln(f) + | `std.Some d: -> d + | `std.None: std.put("eof\n") + -> [][:] + ;; +} + +const readto = {f, delim + match bio.readto(f, delim) + | `std.Some d: -> d + | `std.None: std.put("eof\n") + -> [][:] + ;; +} diff --git a/lib/bio/test/bio-endianrd.myr b/lib/bio/test/bio-endianrd.myr new file mode 100644 index 0000000..53743d8 --- /dev/null +++ b/lib/bio/test/bio-endianrd.myr @@ -0,0 +1,57 @@ +use std +use bio + +generic try = {opt : std.option(@a::(integral,numeric))-> @a::(integral,numeric) + match opt + | `std.Some val: -> val + | `std.None: std.fatal(1, "read failed") + ;; +} +const main = { + var b : byte + var w : uint16 + var l : uint32 + var q : uint64 + var f + + /* use the expected write data as read data */ + match bio.open("data/bio-endianwr-expected", bio.Rd) + | `std.Some bio: f = bio + | `std.None: std.fatal(1, "Unable to open data file") + ;; + + /* byte */ + /* + /* FIXME: compiler bug. multiplication on byte + values is currently broken. */ + b = 0xaa + std.assert(try(bio.getle8(f)) == b, "le byte broken\n") + std.assert(try(bio.getbe8(f)) == b, "be byte broken\n") + */ + + /* word */ + w = 0xaabb + std.assert(try(bio.getle16(f)) == w, "le word broken\n") + std.assert(try(bio.getbe16(f)) == w, "be word broken\n") + + /* long */ + l = 0xaabbccdd + std.assert(try(bio.getle32(f)) == l, "le long broken\n") + std.assert(try(bio.getbe32(f)) == l, "be long broken\n") + + /* quad */ + q = 0x11223344aabbccdd castto(uint64) + std.assert(try(bio.getle64(f)) == q, "le quad broken\n") + std.assert(try(bio.getbe64(f)) == q, "be quad broken\n") + + /* end of file */ + match bio.getle64(f) + | `std.None: + | `std.Some v: std.die("read past end of file\n") + ;; + + bio.close(f); + + std.put("success: all reads matched\n") +} + diff --git a/lib/bio/test/bio-endianwr.myr b/lib/bio/test/bio-endianwr.myr new file mode 100644 index 0000000..e44db49 --- /dev/null +++ b/lib/bio/test/bio-endianwr.myr @@ -0,0 +1,42 @@ +use std +use bio + +const main = { + var b : byte + var w : uint16 + var l : uint32 + var q : uint64 + var f + + match bio.create("tmpout/test-endianwr", bio.Wr, 0o644) + | `std.Some bio: f = bio + | `std.None: std.fatal(1, "Unable to open data file") + ;; + + /* byte */ + /* + /* FIXME: compiler bug. multiplication on byte + values is currently broken. */ + b = 0xaa + bio.putle(f, b) + bio.putbe(f, b) + */ + + /* word */ + w = 0xaabb + bio.putle16(f, w) + bio.putbe16(f, w) + + /* long */ + l = 0xaabbccdd + bio.putle32(f, l) + bio.putbe32(f, l) + + /* quad */ + q = 0x11223344aabbccdd castto(uint64) + bio.putle64(f, q) + bio.putbe64(f, q) + + /* and test for flush on close */ + bio.close(f); +} diff --git a/lib/bio/test/bio-peek.myr b/lib/bio/test/bio-peek.myr new file mode 100644 index 0000000..2125c9b --- /dev/null +++ b/lib/bio/test/bio-peek.myr @@ -0,0 +1,45 @@ +use std +use bio + +const main = { + var f + /* Must be bigger than a bio buffer (ie, > 64k) */ + var buf : byte[64*1024] + + match bio.open("data/datafile", bio.Rd) + | `std.Some bio: f = bio + | `std.None: std.fatal(1, "Unable to open data file") + ;; + + std.assert(peekb(f) == 0x30, "wrong byte value read from datafile") + std.assert(peekc(f) == '0', "wrong char value read from datafile") + + bio.read(f, buf[:4]) /* skip ahead 4 bytes */ + std.assert(peekb(f) == 0x34, "wrong byte value read from datafile") + std.assert(peekc(f) == '4', "wrong char value read from datafile") + + bio.read(f, buf[:]) /* skip ahead 64k */ + std.assert(peekb(f) == 0x30, "wrong byte value read from datafile") + std.assert(peekc(f) == '0', "wrong char value read from datafile") + + bio.close(f); + std.put("Succeded peeeking values\n") +} + +const peekc = {f + match bio.peekc(f) + | `std.Some c: -> c + | `std.None: + std.put("eof") + -> -1 + ;; +} + +const peekb = {f + match bio.peekb(f) + | `std.Some b: -> b + | `std.None: + std.put("eof") + -> -1 + ;; +} diff --git a/lib/bio/test/bio-read.myr b/lib/bio/test/bio-read.myr new file mode 100644 index 0000000..eafdb4a --- /dev/null +++ b/lib/bio/test/bio-read.myr @@ -0,0 +1,46 @@ +use std +use bio + +const main = { + var f + /* Must be bigger than a bio buffer (ie, > 64k) */ + var buf : byte[64*1024] + var b + + match bio.open("data/datafile", bio.Rd) + | `std.Some bio: f = bio + | `std.None: std.fatal(1, "Unable to open data file") + ;; + + /* read a 4 byte chunk j*/ + b = r(f, buf[:4]) + std.write(1, b) + std.write(1, "\n") + + /* read the next 32 bytes */ + b = r(f, buf[:32]) + std.write(1, b) + std.write(1, "\n") + + /* read a 64k chunk */ + b = r(f, buf[:]) + std.write(1, b) + std.write(1, "\n") + + /* read to EOF */ + b = r(f, buf[:]) + std.write(1, b) + std.write(1, "\n") + + /* and fail */ + b = r(f, buf[:]) + + bio.close(f) +} + +const r = {f, buf + match bio.read(f, buf) + | `std.Some b: -> b + | `std.None: std.put("eof\n") + ;; +} diff --git a/lib/bio/test/bio-unitwr.myr b/lib/bio/test/bio-unitwr.myr new file mode 100644 index 0000000..8a1774c --- /dev/null +++ b/lib/bio/test/bio-unitwr.myr @@ -0,0 +1,14 @@ +use std +use bio + +const main = { + var f + match bio.create("tmpout/test-unitwr", bio.Wr, 0o644) + | `std.Some bio: f = bio + | `std.None: std.fatal(1, "Unable to open data file") + ;; + bio.putb(f, 42) + bio.putc(f, '×”') + bio.putb(f, 0xa) + bio.close(f); +} diff --git a/lib/bio/test/bio-write.myr b/lib/bio/test/bio-write.myr new file mode 100644 index 0000000..cbe7441 --- /dev/null +++ b/lib/bio/test/bio-write.myr @@ -0,0 +1,33 @@ +use std +use bio + +const main = { + var i + var f + /* Must be bigger than a bio buffer (ie, > 64k) */ + var buf : byte[64*1024] + + match bio.create("tmpout/test-write", bio.Wr, 0o644) + | `std.Some bio: f = bio + | `std.None: std.fatal(1, "Unable to open data file") + ;; + + /* write a 5 byte chunk */ + bio.write(f, "test\n") + + /* again */ + bio.write(f, "test\n") + + /* write a 64k chunk */ + for i = 0; i < 64*1024; i++ + buf[i] = 0x31 + ;; + bio.write(f, buf[:]) + + /* final message after a big burst */ + bio.write(f, "goodbye\n") + bio.flush(f) + + /* and test for flush on close */ + bio.close(f); +} diff --git a/lib/bio/test/data/bio-create-expected b/lib/bio/test/data/bio-create-expected new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/bio/test/data/bio-create-expected diff --git a/lib/bio/test/data/bio-delim-expected b/lib/bio/test/data/bio-delim-expected new file mode 100644 index 0000000..b90f595 --- /dev/null +++ b/lib/bio/test/data/bio-delim-expected @@ -0,0 +1,10 @@ +first line +second line +data with +semicolons + +and +no-terminator + +eof +eof diff --git a/lib/bio/test/data/bio-endianrd-expected b/lib/bio/test/data/bio-endianrd-expected new file mode 100644 index 0000000..cd9a251 --- /dev/null +++ b/lib/bio/test/data/bio-endianrd-expected @@ -0,0 +1 @@ +success: all reads matched diff --git a/lib/bio/test/data/bio-endianwr-expected b/lib/bio/test/data/bio-endianwr-expected new file mode 100755 index 0000000..8baa404 --- /dev/null +++ b/lib/bio/test/data/bio-endianwr-expected @@ -0,0 +1 @@ +»ªª»ÝÌ»ªª»ÌÝÝÌ»ªD3""3Dª»ÌÝ
\ No newline at end of file diff --git a/lib/bio/test/data/bio-peek-expected b/lib/bio/test/data/bio-peek-expected new file mode 100644 index 0000000..153efdb --- /dev/null +++ b/lib/bio/test/data/bio-peek-expected @@ -0,0 +1 @@ +Succeded peeeking values diff --git a/lib/bio/test/data/bio-read-expected b/lib/bio/test/data/bio-read-expected new file mode 100644 index 0000000..9bf4703 --- /dev/null +++ b/lib/bio/test/data/bio-read-expected @@ -0,0 +1,6 @@ +0123 +45678901234567890123456789012345 +6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 +2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 + +eof diff --git a/lib/bio/test/data/bio-unitwr-expected b/lib/bio/test/data/bio-unitwr-expected new file mode 100644 index 0000000..581c0f6 --- /dev/null +++ b/lib/bio/test/data/bio-unitwr-expected @@ -0,0 +1 @@ +*×” diff --git a/lib/bio/test/data/bio-write-expected b/lib/bio/test/data/bio-write-expected new file mode 100755 index 0000000..ced6c96 --- /dev/null +++ b/lib/bio/test/data/bio-write-expected @@ -0,0 +1,3 @@ +test +test +1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111goodbye diff --git a/lib/bio/test/data/datafile b/lib/bio/test/data/datafile new file mode 100644 index 0000000..52a47f6 --- /dev/null +++ b/lib/bio/test/data/datafile @@ -0,0 +1 @@ +01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 diff --git a/lib/bio/test/data/lines b/lib/bio/test/data/lines new file mode 100644 index 0000000..781db66 --- /dev/null +++ b/lib/bio/test/data/lines @@ -0,0 +1,4 @@ +first line +second line +data with;semicolons; +and--no-terminator diff --git a/lib/bio/test/runtest.sh b/lib/bio/test/runtest.sh new file mode 100755 index 0000000..95f548f --- /dev/null +++ b/lib/bio/test/runtest.sh @@ -0,0 +1,124 @@ +#!/bin/bash +NFAILURES=0 +NPASSES=0 + +function build { + rm -f $1 $1.o $1.s $1.use + myrbuild $FLAGS -b $1 $1.myr $EXTRA_SRC +} + +function pass { + PASSED="$PASSED $1" + NPASSED=$[$NPASSED + 1] +} + +function fail { + echo "FAIL: $1" + FAILED="$FAILED $1" + NFAILED=$[$NFAILED + 1] +} + +function expectstatus { + ./$1 $3 + if [ $? -eq $2 ]; then + pass $1 + return + else + fail $1 + fi +} + +function expectprint { + if [ "`./$1 $3`" != "$2" ]; then + fail $1 + else + pass $1 + fi +} + + +function expectcompare { + if [ x"" != x"$TMPDIR" ]; then + t=$TMPDIR/myrtest-$1-$RANDOM + else + t=/tmp/myrtest-$1-$RANDOM + fi + ./$1 $3 > $t + if cmp $t data/$1-expected; then + pass $1 + else + fail $1 + fi + rm -f $t +} + +function expectfcompare { + ./$1 $3 + if cmp data/$1-expected $2; then + pass $1 + else + fail $1 + fi +} + +function shouldskip { + if [ -z $ARGS ]; then + return 1 + fi + + for i in $ARGS; do + if [ $i = $1 ]; then + return 1 + fi + done + return 0 +} + + +# Should build and run +function B { + if shouldskip $1; then + return + fi + + test="$1"; shift + type="$1"; shift + res="$1"; shift + if [ $# > 0 ]; then + args="$1"; shift + fi + build $test + case $type in + "E") expectstatus "$test" "$res" "$input";; + "P") expectprint "$test" "$res" "$input";; + "C") expectcompare "$test" "$res" "$input";; + "F") expectfcompare "$test" "$res" "$args";; + esac +} + +# Should fail +function F { + if shouldskip $1; then + return + fi + (build $1) > /dev/null + if [ $? -eq '1' ]; then + pass $1 + else + fail $1 + fi +} + +# Should generate a usefile +function U { + return +} + +source tests + +echo "PASSED ($NPASSED): $PASSED" +if [ -z "$NFAILED" ]; then + echo "SUCCESS" +else + echo "FAILURES ($NFAILED): $FAILED" +fi diff --git a/lib/bio/test/tests b/lib/bio/test/tests new file mode 100644 index 0000000..81c1087 --- /dev/null +++ b/lib/bio/test/tests @@ -0,0 +1,31 @@ +FLAGS=-I../ +mkdir -p tmpout +# Format: +# [B|F] testname [E|P] result +# [B|F]: Compiler outcome. +# B: Expect that this test will build. +# F: Expect that this test will not build. +# testname: Test case +# The test that will run. We will try to +# compile 'testname.myr' to 'testname', +# and then execute it, verifying the result +# [E|P|C]: Result type +# E tells us that the result is an exit status +# P tells us that the result is on stdout, +# and should be compared to the value on the +# line +# C tells us that the result is on stdout, +# and should be compared to the contents of +# the file passed on the line. +# result: Result value +# What we compare with. This should be self- +# evident. +B bio-create F tmpout/test-create +B bio-read C +B bio-write F tmpout/test-write +B bio-delim C +B bio-endianwr F tmpout/test-endianwr +B bio-endianrd C +B bio-unitwr F tmpout/test-unitwr +B bio-peek C +#B bio-fmt C diff --git a/lib/cryptohash/bld.sub b/lib/cryptohash/bld.sub new file mode 100644 index 0000000..b6056f7 --- /dev/null +++ b/lib/cryptohash/bld.sub @@ -0,0 +1,7 @@ +lib cryptohash = + md5.myr + sha1.myr + sha256.myr + sha512.myr +;; + diff --git a/lib/cryptohash/md5.myr b/lib/cryptohash/md5.myr new file mode 100644 index 0000000..5f4b600 --- /dev/null +++ b/lib/cryptohash/md5.myr @@ -0,0 +1,215 @@ +use std + +pkg cryptohash = + type md5 + + const md5 : (data : byte[:] -> byte[16]) + const md5init : (st : md5# -> void) + const md5add : (st : md5#, data : byte[:] -> void) + const md5fin : (st : md5# -> byte[16]) +;; + +type md5 = struct + a : uint32 + b : uint32 + c : uint32 + d : uint32 + tail : byte[64] + msglen : uint64 + +;; + +const md5 = {data + var st + + md5init(&st) + md5add(&st, data) + -> md5fin(&st) +} + +const md5init = {st + st.a = 0x67452301 + st.b = 0xefcdab89 + st.c = 0x98badcfe + st.d = 0x10325476 + st.msglen = 0 +} + +const md5add = {st, data + var n, ntail + + ntail = st.msglen % 64 + st.msglen += data.len + if ntail > 0 + n = std.min(64 - ntail, data.len) + std.slcp(st.tail[ntail:ntail + n], data[:n]) + data = data[n:] + if n + ntail < 64 + -> + ;; + step(st, st.tail[:]) + ;; + while data.len >= 64 + step(st, data[:64]) + data = data[64:] + ;; + std.slcp(st.tail[:data.len], data) +} + +const md5fin = {st + var r : byte[16] + var ntail + + /* append first padding block */ + ntail = st.msglen % 64 + st.tail[ntail++] = 0x80 + std.slfill(st.tail[ntail:], 0) + if 64 - ntail < 8 + step(st, st.tail[:]) + std.slfill(st.tail[:], 0) + ;; + + /* append size block */ + st.tail[56] = ((st.msglen * 8) >> 0) castto(byte) + st.tail[57] = ((st.msglen * 8) >> 8) castto(byte) + st.tail[58] = ((st.msglen * 8) >> 16) castto(byte) + st.tail[59] = ((st.msglen * 8) >> 24) castto(byte) + st.tail[60] = ((st.msglen * 8) >> 32) castto(byte) + st.tail[61] = ((st.msglen * 8) >> 40) castto(byte) + st.tail[62] = ((st.msglen * 8) >> 48) castto(byte) + st.tail[63] = ((st.msglen * 8) >> 56) castto(byte) + step(st, st.tail[:]) + + r[0] = (st.a >> 0) castto(byte) + r[1] = (st.a >> 8) castto(byte) + r[2] = (st.a >> 16) castto(byte) + r[3] = (st.a >> 24) castto(byte) + r[4] = (st.b >> 0) castto(byte) + r[5] = (st.b >> 8) castto(byte) + r[6] = (st.b >> 16) castto(byte) + r[7] = (st.b >> 24) castto(byte) + r[8] = (st.c >> 0) castto(byte) + r[9] = (st.c >> 8) castto(byte) + r[10] = (st.c >> 16) castto(byte) + r[11] = (st.c >> 24) castto(byte) + r[12] = (st.d >> 0) castto(byte) + r[13] = (st.d >> 8) castto(byte) + r[14] = (st.d >> 16) castto(byte) + r[15] = (st.d >> 24) castto(byte) + -> r +} + +const step = {st, blk + var a, b, c, d + var s00, s01, s02, s03, s04, s05, s06, s07 + var s08, s09, s10, s11, s12, s13, s14, s15 + + a = st.a + b = st.b + c = st.c + d = st.d + + s00 = unpack(blk[0:4]) + s01 = unpack(blk[4:8]) + s02 = unpack(blk[8:12]) + s03 = unpack(blk[12:16]) + s04 = unpack(blk[16:20]) + s05 = unpack(blk[20:24]) + s06 = unpack(blk[24:28]) + s07 = unpack(blk[28:32]) + s08 = unpack(blk[32:36]) + s09 = unpack(blk[36:40]) + s10 = unpack(blk[40:44]) + s11 = unpack(blk[44:48]) + s12 = unpack(blk[48:52]) + s13 = unpack(blk[52:56]) + s14 = unpack(blk[56:60]) + s15 = unpack(blk[60:64]) + + /* round 1 */ + a += (d ^ (b & (c ^ d))) + 0xd76aa478 + s00; a = b + (a << 7 | a >> 25) + d += (c ^ (a & (b ^ c))) + 0xe8c7b756 + s01; d = a + (d << 12 | d >> 20) + c += (b ^ (d & (a ^ b))) + 0x242070db + s02; c = d + (c << 17 | c >> 15) + b += (a ^ (c & (d ^ a))) + 0xc1bdceee + s03; b = c + (b << 22 | b >> 10) + a += (d ^ (b & (c ^ d))) + 0xf57c0faf + s04; a = b + (a << 7 | a >> 25) + d += (c ^ (a & (b ^ c))) + 0x4787c62a + s05; d = a + (d << 12 | d >> 20) + c += (b ^ (d & (a ^ b))) + 0xa8304613 + s06; c = d + (c << 17 | c >> 15) + b += (a ^ (c & (d ^ a))) + 0xfd469501 + s07; b = c + (b << 22 | b >> 10) + a += (d ^ (b & (c ^ d))) + 0x698098d8 + s08; a = b + (a << 7 | a >> 25) + d += (c ^ (a & (b ^ c))) + 0x8b44f7af + s09; d = a + (d << 12 | d >> 20) + c += (b ^ (d & (a ^ b))) + 0xffff5bb1 + s10; c = d + (c << 17 | c >> 15) + b += (a ^ (c & (d ^ a))) + 0x895cd7be + s11; b = c + (b << 22 | b >> 10) + a += (d ^ (b & (c ^ d))) + 0x6b901122 + s12; a = b + (a << 7 | a >> 25) + d += (c ^ (a & (b ^ c))) + 0xfd987193 + s13; d = a + (d << 12 | d >> 20) + c += (b ^ (d & (a ^ b))) + 0xa679438e + s14; c = d + (c << 17 | c >> 15) + b += (a ^ (c & (d ^ a))) + 0x49b40821 + s15; b = c + (b << 22 | b >> 10) + + /* round 2 */ + a += (c ^ (d & (b ^ c))) + 0xf61e2562 + s01; a = b + (a << 5 | a >> 27) + d += (b ^ (c & (a ^ b))) + 0xc040b340 + s06; d = a + (d << 9 | d >> 23) + c += (a ^ (b & (d ^ a))) + 0x265e5a51 + s11; c = d + (c << 14 | c >> 18) + b += (d ^ (a & (c ^ d))) + 0xe9b6c7aa + s00; b = c + (b << 20 | b >> 12) + a += (c ^ (d & (b ^ c))) + 0xd62f105d + s05; a = b + (a << 5 | a >> 27) + d += (b ^ (c & (a ^ b))) + 0x02441453 + s10; d = a + (d << 9 | d >> 23) + c += (a ^ (b & (d ^ a))) + 0xd8a1e681 + s15; c = d + (c << 14 | c >> 18) + b += (d ^ (a & (c ^ d))) + 0xe7d3fbc8 + s04; b = c + (b << 20 | b >> 12) + a += (c ^ (d & (b ^ c))) + 0x21e1cde6 + s09; a = b + (a << 5 | a >> 27) + d += (b ^ (c & (a ^ b))) + 0xc33707d6 + s14; d = a + (d << 9 | d >> 23) + c += (a ^ (b & (d ^ a))) + 0xf4d50d87 + s03; c = d + (c << 14 | c >> 18) + b += (d ^ (a & (c ^ d))) + 0x455a14ed + s08; b = c + (b << 20 | b >> 12) + a += (c ^ (d & (b ^ c))) + 0xa9e3e905 + s13; a = b + (a << 5 | a >> 27) + d += (b ^ (c & (a ^ b))) + 0xfcefa3f8 + s02; d = a + (d << 9 | d >> 23) + c += (a ^ (b & (d ^ a))) + 0x676f02d9 + s07; c = d + (c << 14 | c >> 18) + b += (d ^ (a & (c ^ d))) + 0x8d2a4c8a + s12; b = c + (b << 20 | b >> 12) + + /* round 3 */ + a += (b ^ c ^ d) + 0xfffa3942 + s05; a = b + (a << 4 | a >> 28) + d += (a ^ b ^ c) + 0x8771f681 + s08; d = a + (d << 11 | d >> 21) + c += (d ^ a ^ b) + 0x6d9d6122 + s11; c = d + (c << 16 | c >> 16) + b += (c ^ d ^ a) + 0xfde5380c + s14; b = c + (b << 23 | b >> 9) + a += (b ^ c ^ d) + 0xa4beea44 + s01; a = b + (a << 4 | a >> 28) + d += (a ^ b ^ c) + 0x4bdecfa9 + s04; d = a + (d << 11 | d >> 21) + c += (d ^ a ^ b) + 0xf6bb4b60 + s07; c = d + (c << 16 | c >> 16) + b += (c ^ d ^ a) + 0xbebfbc70 + s10; b = c + (b << 23 | b >> 9) + a += (b ^ c ^ d) + 0x289b7ec6 + s13; a = b + (a << 4 | a >> 28) + d += (a ^ b ^ c) + 0xeaa127fa + s00; d = a + (d << 11 | d >> 21) + c += (d ^ a ^ b) + 0xd4ef3085 + s03; c = d + (c << 16 | c >> 16) + b += (c ^ d ^ a) + 0x04881d05 + s06; b = c + (b << 23 | b >> 9) + a += (b ^ c ^ d) + 0xd9d4d039 + s09; a = b + (a << 4 | a >> 28) + d += (a ^ b ^ c) + 0xe6db99e5 + s12; d = a + (d << 11 | d >> 21) + c += (d ^ a ^ b) + 0x1fa27cf8 + s15; c = d + (c << 16 | c >> 16) + b += (c ^ d ^ a) + 0xc4ac5665 + s02; b = c + (b << 23 | b >> 9) + + /* round 4 */ + a += (c ^ (b | ~d)) + 0xf4292244 + s00; a = b + (a << 6 | a >> 26) + d += (b ^ (a | ~c)) + 0x432aff97 + s07; d = a + (d << 10 | d >> 22) + c += (a ^ (d | ~b)) + 0xab9423a7 + s14; c = d + (c << 15 | c >> 17) + b += (d ^ (c | ~a)) + 0xfc93a039 + s05; b = c + (b << 21 | b >> 11) + a += (c ^ (b | ~d)) + 0x655b59c3 + s12; a = b + (a << 6 | a >> 26) + d += (b ^ (a | ~c)) + 0x8f0ccc92 + s03; d = a + (d << 10 | d >> 22) + c += (a ^ (d | ~b)) + 0xffeff47d + s10; c = d + (c << 15 | c >> 17) + b += (d ^ (c | ~a)) + 0x85845dd1 + s01; b = c + (b << 21 | b >> 11) + a += (c ^ (b | ~d)) + 0x6fa87e4f + s08; a = b + (a << 6 | a >> 26) + d += (b ^ (a | ~c)) + 0xfe2ce6e0 + s15; d = a + (d << 10 | d >> 22) + c += (a ^ (d | ~b)) + 0xa3014314 + s06; c = d + (c << 15 | c >> 17) + b += (d ^ (c | ~a)) + 0x4e0811a1 + s13; b = c + (b << 21 | b >> 11) + a += (c ^ (b | ~d)) + 0xf7537e82 + s04; a = b + (a << 6 | a >> 26) + d += (b ^ (a | ~c)) + 0xbd3af235 + s11; d = a + (d << 10 | d >> 22) + c += (a ^ (d | ~b)) + 0x2ad7d2bb + s02; c = d + (c << 15 | c >> 17) + b += (d ^ (c | ~a)) + 0xeb86d391 + s09; b = c + (b << 21 | b >> 11) + + st.a += a + st.b += b + st.c += c + st.d += d +} + +const unpack = {b + var v : uint32 + + v = ((b[0] castto(uint32)) << 0) + v |= ((b[1] castto(uint32)) << 8) + v |= ((b[2] castto(uint32)) << 16) + v |= ((b[3] castto(uint32)) << 24) + -> v +} diff --git a/lib/cryptohash/sha1.myr b/lib/cryptohash/sha1.myr new file mode 100644 index 0000000..ecf0ec3 --- /dev/null +++ b/lib/cryptohash/sha1.myr @@ -0,0 +1,243 @@ +use std + +pkg cryptohash = + type sha1 + + const sha1 : (data : byte[:] -> byte[20]) + const sha1init : (st : sha1# -> void) + const sha1add : (st : sha1#, data : byte[:] -> void) + const sha1fin : (st : sha1# -> byte[20]) +;; + +type sha1 = struct + a : uint32 + b : uint32 + c : uint32 + d : uint32 + e : uint32 + tail : byte[64] + msglen : uint64 +;; + +const sha1 = {data + var st + + sha1init(&st) + sha1add(&st, data) + -> sha1fin(&st) +} + +const sha1init = {st + st.a = 0x67452301 + st.b = 0xefcdab89 + st.c = 0x98badcfe + st.d = 0x10325476 + st.e = 0xc3d2e1f0 + st.msglen = 0 +} + +const sha1add = {st, data + var n, ntail + + ntail = st.msglen % 64 + st.msglen += data.len + if ntail > 0 + n = std.min(64 - ntail, data.len) + std.slcp(st.tail[ntail:ntail + n], data[:n]) + data = data[n:] + if n + ntail < 64 + -> + ;; + step(st, st.tail[:]) + ;; + + while data.len >= 64 + step(st, data[:64]) + data = data[64:] + ;; + + std.slcp(st.tail[:data.len], data) +} + +const sha1fin = {st + var r : byte[20] + var ntail + + /* append first padding block */ + ntail = st.msglen % 64 + st.tail[ntail++] = 0x80 + std.slfill(st.tail[ntail:], 0) + if 64 - ntail < 8 + step(st, st.tail[:]) + std.slfill(st.tail[:], 0) + ;; + + + /* append size block */ + st.tail[56] = ((st.msglen * 8) >> 56) castto(byte) + st.tail[57] = ((st.msglen * 8) >> 48) castto(byte) + st.tail[58] = ((st.msglen * 8) >> 40) castto(byte) + st.tail[59] = ((st.msglen * 8) >> 32) castto(byte) + st.tail[60] = ((st.msglen * 8) >> 24) castto(byte) + st.tail[61] = ((st.msglen * 8) >> 16) castto(byte) + st.tail[62] = ((st.msglen * 8) >> 8) castto(byte) + st.tail[63] = ((st.msglen * 8) >> 0) castto(byte) + step(st, st.tail[:]) + + r[0] = (st.a >> 24) castto(byte) + r[1] = (st.a >> 16) castto(byte) + r[2] = (st.a >> 8) castto(byte) + r[3] = (st.a >> 0) castto(byte) + r[4] = (st.b >> 24) castto(byte) + r[5] = (st.b >> 16) castto(byte) + r[6] = (st.b >> 8) castto(byte) + r[7] = (st.b >> 0) castto(byte) + r[8] = (st.c >> 24) castto(byte) + r[9] = (st.c >> 16) castto(byte) + r[10] = (st.c >> 8) castto(byte) + r[11] = (st.c >> 0) castto(byte) + r[12] = (st.d >> 16) castto(byte) + r[13] = (st.d >> 24) castto(byte) + r[14] = (st.d >> 8) castto(byte) + r[15] = (st.d >> 0) castto(byte) + r[16] = (st.e >> 16) castto(byte) + r[17] = (st.e >> 24) castto(byte) + r[18] = (st.e >> 8) castto(byte) + r[19] = (st.e >> 0) castto(byte) + -> r +} + +const K0 = 0x5a827999 +const K1 = 0x6ed9eba1 +const K2 = 0x8f1bbcdc +const K3 = 0xCA62C1D6 +const step = {st, msg + var a, b, c, d, e + var s00, s01, s02, s03, s04, s05, s06, s07 + var s08, s09, s10, s11, s12, s13, s14, s15 + var t + + a = st.a + b = st.b + c = st.c + d = st.d + e = st.e + + s00 = unpack(msg[ 0: 4]) + s01 = unpack(msg[ 4: 8]) + s02 = unpack(msg[ 8:12]) + s03 = unpack(msg[12:16]) + s04 = unpack(msg[16:20]) + s05 = unpack(msg[20:24]) + s06 = unpack(msg[24:28]) + s07 = unpack(msg[28:32]) + s08 = unpack(msg[32:36]) + s09 = unpack(msg[36:40]) + s10 = unpack(msg[40:44]) + s11 = unpack(msg[44:48]) + s12 = unpack(msg[48:52]) + s13 = unpack(msg[52:56]) + s14 = unpack(msg[56:60]) + s15 = unpack(msg[60:64]) + + e += (a << 5 | a >> 27) + (d ^ (b & (c ^ d))) + s00 + K0; b = b << 30 | b >> 2 + d += (e << 5 | e >> 27) + (c ^ (a & (b ^ c))) + s01 + K0; a = a << 30 | a >> 2 + c += (d << 5 | d >> 27) + (b ^ (e & (a ^ b))) + s02 + K0; e = e << 30 | e >> 2 + b += (c << 5 | c >> 27) + (a ^ (d & (e ^ a))) + s03 + K0; d = d << 30 | d >> 2 + a += (b << 5 | b >> 27) + (e ^ (c & (d ^ e))) + s04 + K0; c = c << 30 | c >> 2 + e += (a << 5 | a >> 27) + (d ^ (b & (c ^ d))) + s05 + K0; b = b << 30 | b >> 2 + d += (e << 5 | e >> 27) + (c ^ (a & (b ^ c))) + s06 + K0; a = a << 30 | a >> 2 + c += (d << 5 | d >> 27) + (b ^ (e & (a ^ b))) + s07 + K0; e = e << 30 | e >> 2 + b += (c << 5 | c >> 27) + (a ^ (d & (e ^ a))) + s08 + K0; d = d << 30 | d >> 2 + a += (b << 5 | b >> 27) + (e ^ (c & (d ^ e))) + s09 + K0; c = c << 30 | c >> 2 + e += (a << 5 | a >> 27) + (d ^ (b & (c ^ d))) + s10 + K0; b = b << 30 | b >> 2 + d += (e << 5 | e >> 27) + (c ^ (a & (b ^ c))) + s11 + K0; a = a << 30 | a >> 2 + c += (d << 5 | d >> 27) + (b ^ (e & (a ^ b))) + s12 + K0; e = e << 30 | e >> 2 + b += (c << 5 | c >> 27) + (a ^ (d & (e ^ a))) + s13 + K0; d = d << 30 | d >> 2 + a += (b << 5 | b >> 27) + (e ^ (c & (d ^ e))) + s14 + K0; c = c << 30 | c >> 2 + e += (a << 5 | a >> 27) + (d ^ (b & (c ^ d))) + s15 + K0; b = b << 30 | b >> 2 + + + t = s13 ^ s08 ^ s02 ^ s00; s00 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + (c ^ (a & (b ^ c))) + s00 + K0; a = a << 30 | a >> 2 + t = s14 ^ s09 ^ s03 ^ s01; s01 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + (b ^ (e & (a ^ b))) + s01 + K0; e = e << 30 | e >> 2 + t = s15 ^ s10 ^ s04 ^ s02; s02 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + (a ^ (d & (e ^ a))) + s02 + K0; d = d << 30 | d >> 2 + t = s00 ^ s11 ^ s05 ^ s03; s03 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + (e ^ (c & (d ^ e))) + s03 + K0; c = c << 30 | c >> 2 + t = s01 ^ s12 ^ s06 ^ s04; s04 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + (b ^ c ^ d) + s04 + K1; b = b << 30 | b >> 2 + t = s02 ^ s13 ^ s07 ^ s05; s05 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + (a ^ b ^ c) + s05 + K1; a = a << 30 | a >> 2 + t = s03 ^ s14 ^ s08 ^ s06; s06 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + (e ^ a ^ b) + s06 + K1; e = e << 30 | e >> 2 + t = s04 ^ s15 ^ s09 ^ s07; s07 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + (d ^ e ^ a) + s07 + K1; d = d << 30 | d >> 2 + t = s05 ^ s00 ^ s10 ^ s08; s08 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + (c ^ d ^ e) + s08 + K1; c = c << 30 | c >> 2 + t = s06 ^ s01 ^ s11 ^ s09; s09 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + (b ^ c ^ d) + s09 + K1; b = b << 30 | b >> 2 + t = s07 ^ s02 ^ s12 ^ s10; s10 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + (a ^ b ^ c) + s10 + K1; a = a << 30 | a >> 2 + t = s08 ^ s03 ^ s13 ^ s11; s11 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + (e ^ a ^ b) + s11 + K1; e = e << 30 | e >> 2 + t = s09 ^ s04 ^ s14 ^ s12; s12 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + (d ^ e ^ a) + s12 + K1; d = d << 30 | d >> 2 + t = s10 ^ s05 ^ s15 ^ s13; s13 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + (c ^ d ^ e) + s13 + K1; c = c << 30 | c >> 2 + t = s11 ^ s06 ^ s00 ^ s14; s14 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + (b ^ c ^ d) + s14 + K1; b = b << 30 | b >> 2 + t = s12 ^ s07 ^ s01 ^ s15; s15 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + (a ^ b ^ c) + s15 + K1; a = a << 30 | a >> 2 + t = s13 ^ s08 ^ s02 ^ s00; s00 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + (e ^ a ^ b) + s00 + K1; e = e << 30 | e >> 2 + t = s14 ^ s09 ^ s03 ^ s01; s01 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + (d ^ e ^ a) + s01 + K1; d = d << 30 | d >> 2 + t = s15 ^ s10 ^ s04 ^ s02; s02 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + (c ^ d ^ e) + s02 + K1; c = c << 30 | c >> 2 + t = s00 ^ s11 ^ s05 ^ s03; s03 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + (b ^ c ^ d) + s03 + K1; b = b << 30 | b >> 2 + t = s01 ^ s12 ^ s06 ^ s04; s04 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + (a ^ b ^ c) + s04 + K1; a = a << 30 | a >> 2 + t = s02 ^ s13 ^ s07 ^ s05; s05 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + (e ^ a ^ b) + s05 + K1; e = e << 30 | e >> 2 + t = s03 ^ s14 ^ s08 ^ s06; s06 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + (d ^ e ^ a) + s06 + K1; d = d << 30 | d >> 2 + t = s04 ^ s15 ^ s09 ^ s07; s07 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + (c ^ d ^ e) + s07 + K1; c = c << 30 | c >> 2 + + t = s05 ^ s00 ^ s10 ^ s08; s08 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + ((b & (c | d)) | (c & d)) + s08 + K2; b = b << 30 | b >> 2 + t = s06 ^ s01 ^ s11 ^ s09; s09 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + ((a & (b | c)) | (b & c)) + s09 + K2; a = a << 30 | a >> 2 + t = s07 ^ s02 ^ s12 ^ s10; s10 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + ((e & (a | b)) | (a & b)) + s10 + K2; e = e << 30 | e >> 2 + t = s08 ^ s03 ^ s13 ^ s11; s11 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + ((d & (e | a)) | (e & a)) + s11 + K2; d = d << 30 | d >> 2 + t = s09 ^ s04 ^ s14 ^ s12; s12 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + ((c & (d | e)) | (d & e)) + s12 + K2; c = c << 30 | c >> 2 + t = s10 ^ s05 ^ s15 ^ s13; s13 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + ((b & (c | d)) | (c & d)) + s13 + K2; b = b << 30 | b >> 2 + t = s11 ^ s06 ^ s00 ^ s14; s14 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + ((a & (b | c)) | (b & c)) + s14 + K2; a = a << 30 | a >> 2 + t = s12 ^ s07 ^ s01 ^ s15; s15 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + ((e & (a | b)) | (a & b)) + s15 + K2; e = e << 30 | e >> 2 + t = s13 ^ s08 ^ s02 ^ s00; s00 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + ((d & (e | a)) | (e & a)) + s00 + K2; d = d << 30 | d >> 2 + t = s14 ^ s09 ^ s03 ^ s01; s01 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + ((c & (d | e)) | (d & e)) + s01 + K2; c = c << 30 | c >> 2 + t = s15 ^ s10 ^ s04 ^ s02; s02 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + ((b & (c | d)) | (c & d)) + s02 + K2; b = b << 30 | b >> 2 + t = s00 ^ s11 ^ s05 ^ s03; s03 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + ((a & (b | c)) | (b & c)) + s03 + K2; a = a << 30 | a >> 2 + t = s01 ^ s12 ^ s06 ^ s04; s04 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + ((e & (a | b)) | (a & b)) + s04 + K2; e = e << 30 | e >> 2 + t = s02 ^ s13 ^ s07 ^ s05; s05 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + ((d & (e | a)) | (e & a)) + s05 + K2; d = d << 30 | d >> 2 + t = s03 ^ s14 ^ s08 ^ s06; s06 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + ((c & (d | e)) | (d & e)) + s06 + K2; c = c << 30 | c >> 2 + t = s04 ^ s15 ^ s09 ^ s07; s07 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + ((b & (c | d)) | (c & d)) + s07 + K2; b = b << 30 | b >> 2 + t = s05 ^ s00 ^ s10 ^ s08; s08 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + ((a & (b | c)) | (b & c)) + s08 + K2; a = a << 30 | a >> 2 + t = s06 ^ s01 ^ s11 ^ s09; s09 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + ((e & (a | b)) | (a & b)) + s09 + K2; e = e << 30 | e >> 2 + t = s07 ^ s02 ^ s12 ^ s10; s10 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + ((d & (e | a)) | (e & a)) + s10 + K2; d = d << 30 | d >> 2 + t = s08 ^ s03 ^ s13 ^ s11; s11 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + ((c & (d | e)) | (d & e)) + s11 + K2; c = c << 30 | c >> 2 + + t = s09 ^ s04 ^ s14 ^ s12; s12 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + (b ^ c ^ d) + s12 + K3; b = b << 30 | b >> 2 + t = s10 ^ s05 ^ s15 ^ s13; s13 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + (a ^ b ^ c) + s13 + K3; a = a << 30 | a >> 2 + t = s11 ^ s06 ^ s00 ^ s14; s14 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + (e ^ a ^ b) + s14 + K3; e = e << 30 | e >> 2 + t = s12 ^ s07 ^ s01 ^ s15; s15 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + (d ^ e ^ a) + s15 + K3; d = d << 30 | d >> 2 + t = s13 ^ s08 ^ s02 ^ s00; s00 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + (c ^ d ^ e) + s00 + K3; c = c << 30 | c >> 2 + t = s14 ^ s09 ^ s03 ^ s01; s01 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + (b ^ c ^ d) + s01 + K3; b = b << 30 | b >> 2 + t = s15 ^ s10 ^ s04 ^ s02; s02 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + (a ^ b ^ c) + s02 + K3; a = a << 30 | a >> 2 + t = s00 ^ s11 ^ s05 ^ s03; s03 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + (e ^ a ^ b) + s03 + K3; e = e << 30 | e >> 2 + t = s01 ^ s12 ^ s06 ^ s04; s04 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + (d ^ e ^ a) + s04 + K3; d = d << 30 | d >> 2 + t = s02 ^ s13 ^ s07 ^ s05; s05 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + (c ^ d ^ e) + s05 + K3; c = c << 30 | c >> 2 + t = s03 ^ s14 ^ s08 ^ s06; s06 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + (b ^ c ^ d) + s06 + K3; b = b << 30 | b >> 2 + t = s04 ^ s15 ^ s09 ^ s07; s07 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + (a ^ b ^ c) + s07 + K3; a = a << 30 | a >> 2 + t = s05 ^ s00 ^ s10 ^ s08; s08 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + (e ^ a ^ b) + s08 + K3; e = e << 30 | e >> 2 + t = s06 ^ s01 ^ s11 ^ s09; s09 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + (d ^ e ^ a) + s09 + K3; d = d << 30 | d >> 2 + t = s07 ^ s02 ^ s12 ^ s10; s10 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + (c ^ d ^ e) + s10 + K3; c = c << 30 | c >> 2 + t = s08 ^ s03 ^ s13 ^ s11; s11 = t << 1 | t >> 31; e += (a << 5 | a >> 27) + (b ^ c ^ d) + s11 + K3; b = b << 30 | b >> 2 + t = s09 ^ s04 ^ s14 ^ s12; s12 = t << 1 | t >> 31; d += (e << 5 | e >> 27) + (a ^ b ^ c) + s12 + K3; a = a << 30 | a >> 2 + t = s10 ^ s05 ^ s15 ^ s13; s13 = t << 1 | t >> 31; c += (d << 5 | d >> 27) + (e ^ a ^ b) + s13 + K3; e = e << 30 | e >> 2 + t = s11 ^ s06 ^ s00 ^ s14; s14 = t << 1 | t >> 31; b += (c << 5 | c >> 27) + (d ^ e ^ a) + s14 + K3; d = d << 30 | d >> 2 + t = s12 ^ s07 ^ s01 ^ s15; s15 = t << 1 | t >> 31; a += (b << 5 | b >> 27) + (c ^ d ^ e) + s15 + K3; c = c << 30 | c >> 2 + + st.a += a + st.b += b + st.c += c + st.d += d + st.e += e +} + +const unpack = {b + var v : uint32 + + v = ((b[0] castto(uint32)) << 24) + v |= ((b[1] castto(uint32)) << 16) + v |= ((b[2] castto(uint32)) << 8) + v |= ((b[3] castto(uint32)) << 0) + -> v +} diff --git a/lib/cryptohash/sha256.myr b/lib/cryptohash/sha256.myr new file mode 100644 index 0000000..5939fa8 --- /dev/null +++ b/lib/cryptohash/sha256.myr @@ -0,0 +1,415 @@ +use std + +pkg cryptohash = + type sha256 + type sha224 + + const sha256 : (data : byte[:] -> byte[32]) + const sha256init : (st : sha256# -> void) + const sha256add : (st : sha256#, data : byte[:] -> void) + const sha256fin : (st : sha256# -> byte[32]) + + const sha224 : (data : byte[:] -> byte[28]) + const sha224init : (st : sha224# -> void) + const sha224add : (st : sha224#, data : byte[:] -> void) + const sha224fin : (st : sha224# -> byte[28]) +;; + +type sha256 = struct + x : uint32[8] + tail : byte[64] + msglen : uint64 +;; + +const sha256 = {data + var st + + sha256init(&st) + sha256add(&st, data) + -> sha256fin(&st) +} + +const sha256init = {st + st.x[0] = 0x6A09E667 + st.x[1] = 0xBB67AE85 + st.x[2] = 0x3C6EF372 + st.x[3] = 0xA54FF53A + st.x[4] = 0x510e527f + st.x[5] = 0x9b05688c + st.x[6] = 0x1f83d9ab + st.x[7] = 0x5be0cd19 + st.msglen = 0 +} + +const sha256add = {st, data + var n, ntail + + ntail = st.msglen % 64 + st.msglen += data.len + if ntail > 0 + n = std.min(64 - ntail, data.len) + std.slcp(st.tail[ntail:ntail + n], data[:n]) + data = data[n:] + if n + ntail < 64 + -> + ;; + step(st.x[:], st.tail[:]) + ;; + + while data.len >= 64 + step(st.x[:], data[:64]) + data = data[64:] + ;; + + ntail = st.msglen % 64 + std.slcp(st.tail[:ntail], data) +} + +const sha256fin = {st + var r : byte[32] + + tail(st.x[:], st.msglen, st.tail[:]) + + pack(r[0:4], st.x[0]) + pack(r[4:8], st.x[1]) + pack(r[8:12], st.x[2]) + pack(r[12:16], st.x[3]) + pack(r[16:20], st.x[4]) + pack(r[20:24], st.x[5]) + pack(r[24:28], st.x[6]) + pack(r[28:32], st.x[7]) + -> r +} + +type sha224 = struct + x : uint32[8] + tail : byte[64] + msglen : uint64 +;; + +const sha224 = {data + var st + + sha224init(&st) + sha224add(&st, data) + -> sha224fin(&st) +} + +const sha224init = {st + st.x[0] = 0xc1059ed8 + st.x[1] = 0x367cd507 + st.x[2] = 0x3070dd17 + st.x[3] = 0xf70e5939 + st.x[4] = 0xffc00b31 + st.x[5] = 0x68581511 + st.x[6] = 0x64f98fa7 + st.x[7] = 0xbefa4fa4 + st.msglen = 0 +} + +const sha224add = {st, data + var n, ntail + + ntail = st.msglen % 64 + st.msglen += data.len + if ntail > 0 + n = std.min(64 - ntail, data.len) + std.slcp(st.tail[ntail:ntail + n], data[:n]) + data = data[n:] + if n + ntail < 64 + -> + ;; + step(st.x[:], st.tail[:]) + ;; + + while data.len >= 64 + step(st.x[:], data[:64]) + data = data[64:] + ;; + + ntail = st.msglen % 64 + std.slcp(st.tail[:ntail], data) +} + +const sha224fin = {st + var r : byte[28] + + tail(st.x[:], st.msglen, st.tail[:]) + + pack(r[0:4], st.x[0]) + pack(r[4:8], st.x[1]) + pack(r[8:12], st.x[2]) + pack(r[12:16], st.x[3]) + pack(r[16:20], st.x[4]) + pack(r[20:24], st.x[5]) + pack(r[24:28], st.x[6]) + -> r +} + + +const tail = {x, msglen, tail + var ntail + + /* append first padding block */ + ntail = msglen % 64 + tail[ntail++] = 0x80 + std.slfill(tail[ntail:], 0) + if 64 - ntail < 8 + step(x, tail) + std.slfill(tail, 0) + ;; + + /* append size block */ + tail[56] = ((msglen * 8) >> 56) castto(byte) + tail[57] = ((msglen * 8) >> 48) castto(byte) + tail[58] = ((msglen * 8) >> 40) castto(byte) + tail[59] = ((msglen * 8) >> 32) castto(byte) + tail[60] = ((msglen * 8) >> 24) castto(byte) + tail[61] = ((msglen * 8) >> 16) castto(byte) + tail[62] = ((msglen * 8) >> 8) castto(byte) + tail[63] = ((msglen * 8) >> 0) castto(byte) + step(x, tail) +} + +const step = {x, msg + var a, b, c, d, e, f, g, h + var s00, s01, s02, s03, s04, s05, s06, s07 + var s08, s09, s10, s11, s12, s13, s14, s15 + var s16, s17, s18, s19, s20, s21, s22, s23 + var s24, s25, s26, s27, s28, s29, s30, s31 + var s32, s33, s34, s35, s36, s37, s38, s39 + var s40, s41, s42, s43, s44, s45, s46, s47 + var s48, s49, s50, s51, s52, s53, s54, s55 + var s56, s57, s58, s59, s60, s61, s62, s63 + + a = x[0] + b = x[1] + c = x[2] + d = x[3] + e = x[4] + f = x[5] + g = x[6] + h = x[7] + + s00 = unpack(msg[ 0: 4]) + s01 = unpack(msg[ 4: 8]) + s02 = unpack(msg[ 8:12]) + s03 = unpack(msg[12:16]) + s04 = unpack(msg[16:20]) + s05 = unpack(msg[20:24]) + s06 = unpack(msg[24:28]) + s07 = unpack(msg[28:32]) + s08 = unpack(msg[32:36]) + s09 = unpack(msg[36:40]) + s10 = unpack(msg[40:44]) + s11 = unpack(msg[44:48]) + s12 = unpack(msg[48:52]) + s13 = unpack(msg[52:56]) + s14 = unpack(msg[56:60]) + s15 = unpack(msg[60:64]) + + s16 = s00 + s09 + (((s01 << 25) | (s01 >> 7)) ^ ((s01 << 14) | (s01 >> 18)) ^ (s01 >> 3)) + (((s14 << 15) | (s14 >> 17)) ^ ((s14 << (32- 19)) | (s14 >> 19)) ^ (s14 >> 10)); + s17 = s01 + s10 + (((s02 << 25) | (s02 >> 7)) ^ ((s02 << 14) | (s02 >> 18)) ^ (s02 >> 3)) + (((s15 << 15) | (s15 >> 17)) ^ ((s15 << (32- 19)) | (s15 >> 19)) ^ (s15 >> 10)); + s18 = s02 + s11 + (((s03 << 25) | (s03 >> 7)) ^ ((s03 << 14) | (s03 >> 18)) ^ (s03 >> 3)) + (((s16 << 15) | (s16 >> 17)) ^ ((s16 << (32- 19)) | (s16 >> 19)) ^ (s16 >> 10)); + s19 = s03 + s12 + (((s04 << 25) | (s04 >> 7)) ^ ((s04 << 14) | (s04 >> 18)) ^ (s04 >> 3)) + (((s17 << 15) | (s17 >> 17)) ^ ((s17 << (32- 19)) | (s17 >> 19)) ^ (s17 >> 10)); + s20 = s04 + s13 + (((s05 << 25) | (s05 >> 7)) ^ ((s05 << 14) | (s05 >> 18)) ^ (s05 >> 3)) + (((s18 << 15) | (s18 >> 17)) ^ ((s18 << (32- 19)) | (s18 >> 19)) ^ (s18 >> 10)); + s21 = s05 + s14 + (((s06 << 25) | (s06 >> 7)) ^ ((s06 << 14) | (s06 >> 18)) ^ (s06 >> 3)) + (((s19 << 15) | (s19 >> 17)) ^ ((s19 << (32- 19)) | (s19 >> 19)) ^ (s19 >> 10)); + s22 = s06 + s15 + (((s07 << 25) | (s07 >> 7)) ^ ((s07 << 14) | (s07 >> 18)) ^ (s07 >> 3)) + (((s20 << 15) | (s20 >> 17)) ^ ((s20 << (32- 19)) | (s20 >> 19)) ^ (s20 >> 10)); + s23 = s07 + s16 + (((s08 << 25) | (s08 >> 7)) ^ ((s08 << 14) | (s08 >> 18)) ^ (s08 >> 3)) + (((s21 << 15) | (s21 >> 17)) ^ ((s21 << (32- 19)) | (s21 >> 19)) ^ (s21 >> 10)); + s24 = s08 + s17 + (((s09 << 25) | (s09 >> 7)) ^ ((s09 << 14) | (s09 >> 18)) ^ (s09 >> 3)) + (((s22 << 15) | (s22 >> 17)) ^ ((s22 << (32- 19)) | (s22 >> 19)) ^ (s22 >> 10)); + s25 = s09 + s18 + (((s10 << 25) | (s10 >> 7)) ^ ((s10 << 14) | (s10 >> 18)) ^ (s10 >> 3)) + (((s23 << 15) | (s23 >> 17)) ^ ((s23 << (32- 19)) | (s23 >> 19)) ^ (s23 >> 10)); + s26 = s10 + s19 + (((s11 << 25) | (s11 >> 7)) ^ ((s11 << 14) | (s11 >> 18)) ^ (s11 >> 3)) + (((s24 << 15) | (s24 >> 17)) ^ ((s24 << (32- 19)) | (s24 >> 19)) ^ (s24 >> 10)); + s27 = s11 + s20 + (((s12 << 25) | (s12 >> 7)) ^ ((s12 << 14) | (s12 >> 18)) ^ (s12 >> 3)) + (((s25 << 15) | (s25 >> 17)) ^ ((s25 << (32- 19)) | (s25 >> 19)) ^ (s25 >> 10)); + s28 = s12 + s21 + (((s13 << 25) | (s13 >> 7)) ^ ((s13 << 14) | (s13 >> 18)) ^ (s13 >> 3)) + (((s26 << 15) | (s26 >> 17)) ^ ((s26 << (32- 19)) | (s26 >> 19)) ^ (s26 >> 10)); + s29 = s13 + s22 + (((s14 << 25) | (s14 >> 7)) ^ ((s14 << 14) | (s14 >> 18)) ^ (s14 >> 3)) + (((s27 << 15) | (s27 >> 17)) ^ ((s27 << (32- 19)) | (s27 >> 19)) ^ (s27 >> 10)); + s30 = s14 + s23 + (((s15 << 25) | (s15 >> 7)) ^ ((s15 << 14) | (s15 >> 18)) ^ (s15 >> 3)) + (((s28 << 15) | (s28 >> 17)) ^ ((s28 << (32- 19)) | (s28 >> 19)) ^ (s28 >> 10)); + s31 = s15 + s24 + (((s16 << 25) | (s16 >> 7)) ^ ((s16 << 14) | (s16 >> 18)) ^ (s16 >> 3)) + (((s29 << 15) | (s29 >> 17)) ^ ((s29 << (32- 19)) | (s29 >> 19)) ^ (s29 >> 10)); + s32 = s16 + s25 + (((s17 << 25) | (s17 >> 7)) ^ ((s17 << 14) | (s17 >> 18)) ^ (s17 >> 3)) + (((s30 << 15) | (s30 >> 17)) ^ ((s30 << (32- 19)) | (s30 >> 19)) ^ (s30 >> 10)); + s33 = s17 + s26 + (((s18 << 25) | (s18 >> 7)) ^ ((s18 << 14) | (s18 >> 18)) ^ (s18 >> 3)) + (((s31 << 15) | (s31 >> 17)) ^ ((s31 << (32- 19)) | (s31 >> 19)) ^ (s31 >> 10)); + s34 = s18 + s27 + (((s19 << 25) | (s19 >> 7)) ^ ((s19 << 14) | (s19 >> 18)) ^ (s19 >> 3)) + (((s32 << 15) | (s32 >> 17)) ^ ((s32 << (32- 19)) | (s32 >> 19)) ^ (s32 >> 10)); + s35 = s19 + s28 + (((s20 << 25) | (s20 >> 7)) ^ ((s20 << 14) | (s20 >> 18)) ^ (s20 >> 3)) + (((s33 << 15) | (s33 >> 17)) ^ ((s33 << (32- 19)) | (s33 >> 19)) ^ (s33 >> 10)); + s36 = s20 + s29 + (((s21 << 25) | (s21 >> 7)) ^ ((s21 << 14) | (s21 >> 18)) ^ (s21 >> 3)) + (((s34 << 15) | (s34 >> 17)) ^ ((s34 << (32- 19)) | (s34 >> 19)) ^ (s34 >> 10)); + s37 = s21 + s30 + (((s22 << 25) | (s22 >> 7)) ^ ((s22 << 14) | (s22 >> 18)) ^ (s22 >> 3)) + (((s35 << 15) | (s35 >> 17)) ^ ((s35 << (32- 19)) | (s35 >> 19)) ^ (s35 >> 10)); + s38 = s22 + s31 + (((s23 << 25) | (s23 >> 7)) ^ ((s23 << 14) | (s23 >> 18)) ^ (s23 >> 3)) + (((s36 << 15) | (s36 >> 17)) ^ ((s36 << (32- 19)) | (s36 >> 19)) ^ (s36 >> 10)); + s39 = s23 + s32 + (((s24 << 25) | (s24 >> 7)) ^ ((s24 << 14) | (s24 >> 18)) ^ (s24 >> 3)) + (((s37 << 15) | (s37 >> 17)) ^ ((s37 << (32- 19)) | (s37 >> 19)) ^ (s37 >> 10)); + s40 = s24 + s33 + (((s25 << 25) | (s25 >> 7)) ^ ((s25 << 14) | (s25 >> 18)) ^ (s25 >> 3)) + (((s38 << 15) | (s38 >> 17)) ^ ((s38 << (32- 19)) | (s38 >> 19)) ^ (s38 >> 10)); + s41 = s25 + s34 + (((s26 << 25) | (s26 >> 7)) ^ ((s26 << 14) | (s26 >> 18)) ^ (s26 >> 3)) + (((s39 << 15) | (s39 >> 17)) ^ ((s39 << (32- 19)) | (s39 >> 19)) ^ (s39 >> 10)); + s42 = s26 + s35 + (((s27 << 25) | (s27 >> 7)) ^ ((s27 << 14) | (s27 >> 18)) ^ (s27 >> 3)) + (((s40 << 15) | (s40 >> 17)) ^ ((s40 << (32- 19)) | (s40 >> 19)) ^ (s40 >> 10)); + s43 = s27 + s36 + (((s28 << 25) | (s28 >> 7)) ^ ((s28 << 14) | (s28 >> 18)) ^ (s28 >> 3)) + (((s41 << 15) | (s41 >> 17)) ^ ((s41 << (32- 19)) | (s41 >> 19)) ^ (s41 >> 10)); + s44 = s28 + s37 + (((s29 << 25) | (s29 >> 7)) ^ ((s29 << 14) | (s29 >> 18)) ^ (s29 >> 3)) + (((s42 << 15) | (s42 >> 17)) ^ ((s42 << (32- 19)) | (s42 >> 19)) ^ (s42 >> 10)); + s45 = s29 + s38 + (((s30 << 25) | (s30 >> 7)) ^ ((s30 << 14) | (s30 >> 18)) ^ (s30 >> 3)) + (((s43 << 15) | (s43 >> 17)) ^ ((s43 << (32- 19)) | (s43 >> 19)) ^ (s43 >> 10)); + s46 = s30 + s39 + (((s31 << 25) | (s31 >> 7)) ^ ((s31 << 14) | (s31 >> 18)) ^ (s31 >> 3)) + (((s44 << 15) | (s44 >> 17)) ^ ((s44 << (32- 19)) | (s44 >> 19)) ^ (s44 >> 10)); + s47 = s31 + s40 + (((s32 << 25) | (s32 >> 7)) ^ ((s32 << 14) | (s32 >> 18)) ^ (s32 >> 3)) + (((s45 << 15) | (s45 >> 17)) ^ ((s45 << (32- 19)) | (s45 >> 19)) ^ (s45 >> 10)); + s48 = s32 + s41 + (((s33 << 25) | (s33 >> 7)) ^ ((s33 << 14) | (s33 >> 18)) ^ (s33 >> 3)) + (((s46 << 15) | (s46 >> 17)) ^ ((s46 << (32- 19)) | (s46 >> 19)) ^ (s46 >> 10)); + s49 = s33 + s42 + (((s34 << 25) | (s34 >> 7)) ^ ((s34 << 14) | (s34 >> 18)) ^ (s34 >> 3)) + (((s47 << 15) | (s47 >> 17)) ^ ((s47 << (32- 19)) | (s47 >> 19)) ^ (s47 >> 10)); + s50 = s34 + s43 + (((s35 << 25) | (s35 >> 7)) ^ ((s35 << 14) | (s35 >> 18)) ^ (s35 >> 3)) + (((s48 << 15) | (s48 >> 17)) ^ ((s48 << (32- 19)) | (s48 >> 19)) ^ (s48 >> 10)); + s51 = s35 + s44 + (((s36 << 25) | (s36 >> 7)) ^ ((s36 << 14) | (s36 >> 18)) ^ (s36 >> 3)) + (((s49 << 15) | (s49 >> 17)) ^ ((s49 << (32- 19)) | (s49 >> 19)) ^ (s49 >> 10)); + s52 = s36 + s45 + (((s37 << 25) | (s37 >> 7)) ^ ((s37 << 14) | (s37 >> 18)) ^ (s37 >> 3)) + (((s50 << 15) | (s50 >> 17)) ^ ((s50 << (32- 19)) | (s50 >> 19)) ^ (s50 >> 10)); + s53 = s37 + s46 + (((s38 << 25) | (s38 >> 7)) ^ ((s38 << 14) | (s38 >> 18)) ^ (s38 >> 3)) + (((s51 << 15) | (s51 >> 17)) ^ ((s51 << (32- 19)) | (s51 >> 19)) ^ (s51 >> 10)); + s54 = s38 + s47 + (((s39 << 25) | (s39 >> 7)) ^ ((s39 << 14) | (s39 >> 18)) ^ (s39 >> 3)) + (((s52 << 15) | (s52 >> 17)) ^ ((s52 << (32- 19)) | (s52 >> 19)) ^ (s52 >> 10)); + s55 = s39 + s48 + (((s40 << 25) | (s40 >> 7)) ^ ((s40 << 14) | (s40 >> 18)) ^ (s40 >> 3)) + (((s53 << 15) | (s53 >> 17)) ^ ((s53 << (32- 19)) | (s53 >> 19)) ^ (s53 >> 10)); + s56 = s40 + s49 + (((s41 << 25) | (s41 >> 7)) ^ ((s41 << 14) | (s41 >> 18)) ^ (s41 >> 3)) + (((s54 << 15) | (s54 >> 17)) ^ ((s54 << (32- 19)) | (s54 >> 19)) ^ (s54 >> 10)); + s57 = s41 + s50 + (((s42 << 25) | (s42 >> 7)) ^ ((s42 << 14) | (s42 >> 18)) ^ (s42 >> 3)) + (((s55 << 15) | (s55 >> 17)) ^ ((s55 << (32- 19)) | (s55 >> 19)) ^ (s55 >> 10)); + s58 = s42 + s51 + (((s43 << 25) | (s43 >> 7)) ^ ((s43 << 14) | (s43 >> 18)) ^ (s43 >> 3)) + (((s56 << 15) | (s56 >> 17)) ^ ((s56 << (32- 19)) | (s56 >> 19)) ^ (s56 >> 10)); + s59 = s43 + s52 + (((s44 << 25) | (s44 >> 7)) ^ ((s44 << 14) | (s44 >> 18)) ^ (s44 >> 3)) + (((s57 << 15) | (s57 >> 17)) ^ ((s57 << (32- 19)) | (s57 >> 19)) ^ (s57 >> 10)); + s60 = s44 + s53 + (((s45 << 25) | (s45 >> 7)) ^ ((s45 << 14) | (s45 >> 18)) ^ (s45 >> 3)) + (((s58 << 15) | (s58 >> 17)) ^ ((s58 << (32- 19)) | (s58 >> 19)) ^ (s58 >> 10)); + s61 = s45 + s54 + (((s46 << 25) | (s46 >> 7)) ^ ((s46 << 14) | (s46 >> 18)) ^ (s46 >> 3)) + (((s59 << 15) | (s59 >> 17)) ^ ((s59 << (32- 19)) | (s59 >> 19)) ^ (s59 >> 10)); + s62 = s46 + s55 + (((s47 << 25) | (s47 >> 7)) ^ ((s47 << 14) | (s47 >> 18)) ^ (s47 >> 3)) + (((s60 << 15) | (s60 >> 17)) ^ ((s60 << (32- 19)) | (s60 >> 19)) ^ (s60 >> 10)); + s63 = s47 + s56 + (((s48 << 25) | (s48 >> 7)) ^ ((s48 << 14) | (s48 >> 18)) ^ (s48 >> 3)) + (((s61 << 15) | (s61 >> 17)) ^ ((s61 << (32- 19)) | (s61 >> 19)) ^ (s61 >> 10)); + + + h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x428a2f98 + s00; + d += h; h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c)); + g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x71374491 + s01; + c += g; g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b)); + f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0xb5c0fbcf + s02; + b += f; f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a)); + e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0xe9b5dba5 + s03; + a += e; e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h)); + d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x3956c25b + s04; + h += d; d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g)); + c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x59f111f1 + s05; + g += c; c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f)); + b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x923f82a4 + s06; + f += b; b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e)); + a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0xab1c5ed5 + s07; + e += a; a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d)); + h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0xd807aa98 + s08; + d += h; h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c)); + g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x12835b01 + s09; + c += g; g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b)); + f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x243185be + s10; + b += f; f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a)); + e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x550c7dc3 + s11; + a += e; e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h)); + d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x72be5d74 + s12; + h += d; d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g)); + c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x80deb1fe + s13; + g += c; c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f)); + b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x9bdc06a7 + s14; + f += b; b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e)); + a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0xc19bf174 + s15; + e += a; a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d)); + h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0xe49b69c1 + s16; + d += h; h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c)); + g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0xefbe4786 + s17; + c += g; g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b)); + f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x0fc19dc6 + s18; + b += f; f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a)); + e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x240ca1cc + s19; + a += e; e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h)); + d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x2de92c6f + s20; + h += d; d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g)); + c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x4a7484aa + s21; + g += c; c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f)); + b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x5cb0a9dc + s22; + f += b; b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e)); + a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x76f988da + s23; + e += a; a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d)); + h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x983e5152 + s24; + d += h; h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c)); + g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0xa831c66d + s25; + c += g; g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b)); + f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0xb00327c8 + s26; + b += f; f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a)); + e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0xbf597fc7 + s27; + a += e; e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h)); + d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0xc6e00bf3 + s28; + h += d; d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g)); + c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0xd5a79147 + s29; + g += c; c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f)); + b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x06ca6351 + s30; + f += b; b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e)); + a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x14292967 + s31; + e += a; a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d)); + h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x27b70a85 + s32; + d += h; h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c)); + g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x2e1b2138 + s33; + c += g; g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b)); + f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x4d2c6dfc + s34; + b += f; f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a)); + e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x53380d13 + s35; + a += e; e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h)); + d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x650a7354 + s36; + h += d; d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g)); + c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x766a0abb + s37; + g += c; c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f)); + b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x81c2c92e + s38; + f += b; b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e)); + a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x92722c85 + s39; + e += a; a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d)); + h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0xa2bfe8a1 + s40; + d += h; h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c)); + g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0xa81a664b + s41; + c += g; g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b)); + f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0xc24b8b70 + s42; + b += f; f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a)); + e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0xc76c51a3 + s43; + a += e; e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h)); + d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0xd192e819 + s44; + h += d; d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g)); + c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0xd6990624 + s45; + g += c; c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f)); + b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0xf40e3585 + s46; + f += b; b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e)); + a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x106aa070 + s47; + e += a; a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d)); + h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x19a4c116 + s48; + d += h; h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c)); + g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x1e376c08 + s49; + c += g; g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b)); + f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x2748774c + s50; + b += f; f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a)); + e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x34b0bcb5 + s51; + a += e; e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h)); + d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x391c0cb3 + s52; + h += d; d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g)); + c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0x4ed8aa4a + s53; + g += c; c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f)); + b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0x5b9cca4f + s54; + f += b; b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e)); + a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0x682e6ff3 + s55; + e += a; a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d)); + h += (((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25))) + (g ^ (e & (f ^ g))) + 0x748f82ee + s56; + d += h; h += (((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22))) + ((a & (b | c)) | (b & c)); + g += (((d << 26) | (d >> 6)) ^ ((d << 21) | (d >> 11)) ^ ((d << 7) | (d >> 25))) + (f ^ (d & (e ^ f))) + 0x78a5636f + s57; + c += g; g += (((h << 30) | (h >> 2)) ^ ((h << 19) | (h >> 13)) ^ ((h << 10) | (h >> 22))) + ((h & (a | b)) | (a & b)); + f += (((c << 26) | (c >> 6)) ^ ((c << 21) | (c >> 11)) ^ ((c << 7) | (c >> 25))) + (e ^ (c & (d ^ e))) + 0x84c87814 + s58; + b += f; f += (((g << 30) | (g >> 2)) ^ ((g << 19) | (g >> 13)) ^ ((g << 10) | (g >> 22))) + ((g & (h | a)) | (h & a)); + e += (((b << 26) | (b >> 6)) ^ ((b << 21) | (b >> 11)) ^ ((b << 7) | (b >> 25))) + (d ^ (b & (c ^ d))) + 0x8cc70208 + s59; + a += e; e += (((f << 30) | (f >> 2)) ^ ((f << 19) | (f >> 13)) ^ ((f << 10) | (f >> 22))) + ((f & (g | h)) | (g & h)); + d += (((a << 26) | (a >> 6)) ^ ((a << 21) | (a >> 11)) ^ ((a << 7) | (a >> 25))) + (c ^ (a & (b ^ c))) + 0x90befffa + s60; + h += d; d += (((e << 30) | (e >> 2)) ^ ((e << 19) | (e >> 13)) ^ ((e << 10) | (e >> 22))) + ((e & (f | g)) | (f & g)); + c += (((h << 26) | (h >> 6)) ^ ((h << 21) | (h >> 11)) ^ ((h << 7) | (h >> 25))) + (b ^ (h & (a ^ b))) + 0xa4506ceb + s61; + g += c; c += (((d << 30) | (d >> 2)) ^ ((d << 19) | (d >> 13)) ^ ((d << 10) | (d >> 22))) + ((d & (e | f)) | (e & f)); + b += (((g << 26) | (g >> 6)) ^ ((g << 21) | (g >> 11)) ^ ((g << 7) | (g >> 25))) + (a ^ (g & (h ^ a))) + 0xbef9a3f7 + s62; + f += b; b += (((c << 30) | (c >> 2)) ^ ((c << 19) | (c >> 13)) ^ ((c << 10) | (c >> 22))) + ((c & (d | e)) | (d & e)); + a += (((f << 26) | (f >> 6)) ^ ((f << 21) | (f >> 11)) ^ ((f << 7) | (f >> 25))) + (h ^ (f & (g ^ h))) + 0xc67178f2 + s63; + e += a; a += (((b << 30) | (b >> 2)) ^ ((b << 19) | (b >> 13)) ^ ((b << 10) | (b >> 22))) + ((b & (c | d)) | (c & d)); + + x[0] += a + x[1] += b + x[2] += c + x[3] += d + x[4] += e + x[5] += f + x[6] += g + x[7] += h +} + +const unpack = {b + var v : uint32 + + v = ((b[0] castto(uint32)) << 24) + v |= ((b[1] castto(uint32)) << 16) + v |= ((b[2] castto(uint32)) << 8) + v |= ((b[3] castto(uint32)) << 0) + -> v +} + +const pack = {out, v + out[0] = (v >> 24) castto(byte) + out[1] = (v >> 16) castto(byte) + out[2] = (v >> 8) castto(byte) + out[3] = (v >> 0) castto(byte) +} diff --git a/lib/cryptohash/sha512.myr b/lib/cryptohash/sha512.myr new file mode 100644 index 0000000..e5d9543 --- /dev/null +++ b/lib/cryptohash/sha512.myr @@ -0,0 +1,474 @@ +use std + +pkg cryptohash = + type sha512 + type sha384 + + const sha512 : (data : byte[:] -> byte[64]) + const sha512init : (st : sha512# -> void) + const sha512add : (st : sha512#, data : byte[:] -> void) + const sha512fin : (st : sha512# -> byte[64]) + + const sha384 : (data : byte[:] -> byte[48]) + const sha384init : (st : sha384# -> void) + const sha384add : (st : sha384#, data : byte[:] -> void) + const sha384fin : (st : sha384# -> byte[48]) +;; + + +type sha512 = struct + x : uint64[8] + tail : byte[128] + msglen : uint64 +;; + +type sha384 = struct + x : uint64[8] + tail : byte[128] + msglen : uint64 +;; + +const sha512 = {data + var st + + sha512init(&st) + sha512add(&st, data) + -> sha512fin(&st) +} + +const sha512init = {st + st.x[0] = 0x6a09e667f3bcc908ul + st.x[1] = 0xbb67ae8584caa73bul + st.x[2] = 0x3c6ef372fe94f82bul + st.x[3] = 0xa54ff53a5f1d36f1ul + st.x[4] = 0x510e527fade682d1ul + st.x[5] = 0x9b05688c2b3e6c1ful + st.x[6] = 0x1f83d9abfb41bd6bul + st.x[7] = 0x5be0cd19137e2179ul + st.msglen = 0 +} + +const sha512add = {st, data + var n, ntail + + ntail = st.msglen % 128 + st.msglen += data.len + if ntail > 0 + n = std.min(128 - ntail, data.len) + std.slcp(st.tail[ntail:ntail+n], data[:n]) + data = data[n:] + if n + ntail < 128 + -> + ;; + step(st.x[:], st.tail[:]) + ;; + + while data.len >= 128 + step(st.x[:], data[:128]) + data = data[128:] + ;; + + ntail = st.msglen % 128 + std.slcp(st.tail[:ntail], data) +} + +const sha512fin = {st + var r : byte[64] + + tail(st.x[:], st.msglen, st.tail[:]) + + pack(r[ 0: 8], st.x[0]) + pack(r[ 8:16], st.x[1]) + pack(r[16:24], st.x[2]) + pack(r[24:32], st.x[3]) + pack(r[32:40], st.x[4]) + pack(r[40:48], st.x[5]) + pack(r[48:56], st.x[6]) + pack(r[56:64], st.x[7]) + -> r +} + +const sha384 = {data + var st + + sha384init(&st) + sha384add(&st, data) + -> sha384fin(&st) +} + +const sha384init = {st + st.x[0] = 0xCBBB9D5DC1059ED8ul + st.x[1] = 0x629A292A367CD507ul + st.x[2] = 0x9159015A3070DD17ul + st.x[3] = 0x152FECD8F70E5939ul + st.x[4] = 0x67332667FFC00B31ul + st.x[5] = 0x8EB44A8768581511ul + st.x[6] = 0xDB0C2E0D64F98FA7ul + st.x[7] = 0x47B5481DBEFA4FA4ul + st.msglen = 0 +} + +const sha384add = {st, data + var n, ntail + + ntail = st.msglen % 128 + st.msglen += data.len + if ntail > 0 + n = std.min(128 - ntail, data.len) + std.slcp(st.tail[ntail:ntail+n], data[:n]) + data = data[n:] + if n + ntail < 128 + -> + ;; + step(st.x[:], st.tail[:]) + ;; + + while data.len >= 128 + step(st.x[:], data[:128]) + data = data[128:] + ;; + + ntail = st.msglen % 128 + std.slcp(st.tail[:ntail], data) +} + +const sha384fin = {st + var r : byte[48] + + tail(st.x[:], st.msglen, st.tail[:]) + + pack(r[ 0: 8], st.x[0]) + pack(r[ 8:16], st.x[1]) + pack(r[16:24], st.x[2]) + pack(r[24:32], st.x[3]) + pack(r[32:40], st.x[4]) + pack(r[40:48], st.x[5]) + -> r +} + + +const tail = {x, msglen, tail + var ntail + + /* append first padding block */ + ntail = msglen % 128 + tail[ntail++] = 0x80 + std.slfill(tail[ntail:], 0) + if 128 - ntail < 16 + step(x, tail) + std.slfill(tail, 0) + ;; + + /* append size block */ + tail[120] = ((msglen * 8) >> 56) castto(byte) + tail[121] = ((msglen * 8) >> 48) castto(byte) + tail[122] = ((msglen * 8) >> 40) castto(byte) + tail[123] = ((msglen * 8) >> 32) castto(byte) + tail[124] = ((msglen * 8) >> 24) castto(byte) + tail[125] = ((msglen * 8) >> 16) castto(byte) + tail[126] = ((msglen * 8) >> 8) castto(byte) + tail[127] = ((msglen * 8) >> 0) castto(byte) + step(x, tail) +} + +const step = {x : uint64[:], msg + var a, b, c, d, e, f, g, h + var s00, s01, s02, s03, s04, s05, s06, s07 + var s08, s09, s10, s11, s12, s13, s14, s15 + var s16, s17, s18, s19, s20, s21, s22, s23 + var s24, s25, s26, s27, s28, s29, s30, s31 + var s32, s33, s34, s35, s36, s37, s38, s39 + var s40, s41, s42, s43, s44, s45, s46, s47 + var s48, s49, s50, s51, s52, s53, s54, s55 + var s56, s57, s58, s59, s60, s61, s62, s63 + var s64, s65, s66, s67, s68, s69, s70, s71 + var s72, s73, s74, s75, s76, s77, s78, s79 + + a = x[0] + b = x[1] + c = x[2] + d = x[3] + e = x[4] + f = x[5] + g = x[6] + h = x[7] + + s00 = unpack(msg[ 0: 8]) + s01 = unpack(msg[ 8: 16]) + s02 = unpack(msg[ 16: 24]) + s03 = unpack(msg[ 24: 32]) + s04 = unpack(msg[ 32: 40]) + s05 = unpack(msg[ 40: 48]) + s06 = unpack(msg[ 48: 56]) + s07 = unpack(msg[ 56: 64]) + s08 = unpack(msg[ 64: 72]) + s09 = unpack(msg[ 72: 80]) + s10 = unpack(msg[ 80: 88]) + s11 = unpack(msg[ 88: 96]) + s12 = unpack(msg[ 96:104]) + s13 = unpack(msg[104:112]) + s14 = unpack(msg[112:120]) + s15 = unpack(msg[120:128]) + + s16 = s00 + s09 + (((s01 << 63) | (s01 >> 1))^((s01 << 56) | (s01 >> 8))^(s01 >> 7)) + (((s14 << 45) | (s14 >> 19))^((s14 << 3) | (s14 >> 61))^(s14 >> 6)) + s17 = s01 + s10 + (((s02 << 63) | (s02 >> 1))^((s02 << 56) | (s02 >> 8))^(s02 >> 7)) + (((s15 << 45) | (s15 >> 19))^((s15 << 3) | (s15 >> 61))^(s15 >> 6)) + s18 = s02 + s11 + (((s03 << 63) | (s03 >> 1))^((s03 << 56) | (s03 >> 8))^(s03 >> 7)) + (((s16 << 45) | (s16 >> 19))^((s16 << 3) | (s16 >> 61))^(s16 >> 6)) + s19 = s03 + s12 + (((s04 << 63) | (s04 >> 1))^((s04 << 56) | (s04 >> 8))^(s04 >> 7)) + (((s17 << 45) | (s17 >> 19))^((s17 << 3) | (s17 >> 61))^(s17 >> 6)) + s20 = s04 + s13 + (((s05 << 63) | (s05 >> 1))^((s05 << 56) | (s05 >> 8))^(s05 >> 7)) + (((s18 << 45) | (s18 >> 19))^((s18 << 3) | (s18 >> 61))^(s18 >> 6)) + s21 = s05 + s14 + (((s06 << 63) | (s06 >> 1))^((s06 << 56) | (s06 >> 8))^(s06 >> 7)) + (((s19 << 45) | (s19 >> 19))^((s19 << 3) | (s19 >> 61))^(s19 >> 6)) + s22 = s06 + s15 + (((s07 << 63) | (s07 >> 1))^((s07 << 56) | (s07 >> 8))^(s07 >> 7)) + (((s20 << 45) | (s20 >> 19))^((s20 << 3) | (s20 >> 61))^(s20 >> 6)) + s23 = s07 + s16 + (((s08 << 63) | (s08 >> 1))^((s08 << 56) | (s08 >> 8))^(s08 >> 7)) + (((s21 << 45) | (s21 >> 19))^((s21 << 3) | (s21 >> 61))^(s21 >> 6)) + s24 = s08 + s17 + (((s09 << 63) | (s09 >> 1))^((s09 << 56) | (s09 >> 8))^(s09 >> 7)) + (((s22 << 45) | (s22 >> 19))^((s22 << 3) | (s22 >> 61))^(s22 >> 6)) + s25 = s09 + s18 + (((s10 << 63) | (s10 >> 1))^((s10 << 56) | (s10 >> 8))^(s10 >> 7)) + (((s23 << 45) | (s23 >> 19))^((s23 << 3) | (s23 >> 61))^(s23 >> 6)) + s26 = s10 + s19 + (((s11 << 63) | (s11 >> 1))^((s11 << 56) | (s11 >> 8))^(s11 >> 7)) + (((s24 << 45) | (s24 >> 19))^((s24 << 3) | (s24 >> 61))^(s24 >> 6)) + s27 = s11 + s20 + (((s12 << 63) | (s12 >> 1))^((s12 << 56) | (s12 >> 8))^(s12 >> 7)) + (((s25 << 45) | (s25 >> 19))^((s25 << 3) | (s25 >> 61))^(s25 >> 6)) + s28 = s12 + s21 + (((s13 << 63) | (s13 >> 1))^((s13 << 56) | (s13 >> 8))^(s13 >> 7)) + (((s26 << 45) | (s26 >> 19))^((s26 << 3) | (s26 >> 61))^(s26 >> 6)) + s29 = s13 + s22 + (((s14 << 63) | (s14 >> 1))^((s14 << 56) | (s14 >> 8))^(s14 >> 7)) + (((s27 << 45) | (s27 >> 19))^((s27 << 3) | (s27 >> 61))^(s27 >> 6)) + s30 = s14 + s23 + (((s15 << 63) | (s15 >> 1))^((s15 << 56) | (s15 >> 8))^(s15 >> 7)) + (((s28 << 45) | (s28 >> 19))^((s28 << 3) | (s28 >> 61))^(s28 >> 6)) + s31 = s15 + s24 + (((s16 << 63) | (s16 >> 1))^((s16 << 56) | (s16 >> 8))^(s16 >> 7)) + (((s29 << 45) | (s29 >> 19))^((s29 << 3) | (s29 >> 61))^(s29 >> 6)) + s32 = s16 + s25 + (((s17 << 63) | (s17 >> 1))^((s17 << 56) | (s17 >> 8))^(s17 >> 7)) + (((s30 << 45) | (s30 >> 19))^((s30 << 3) | (s30 >> 61))^(s30 >> 6)) + s33 = s17 + s26 + (((s18 << 63) | (s18 >> 1))^((s18 << 56) | (s18 >> 8))^(s18 >> 7)) + (((s31 << 45) | (s31 >> 19))^((s31 << 3) | (s31 >> 61))^(s31 >> 6)) + s34 = s18 + s27 + (((s19 << 63) | (s19 >> 1))^((s19 << 56) | (s19 >> 8))^(s19 >> 7)) + (((s32 << 45) | (s32 >> 19))^((s32 << 3) | (s32 >> 61))^(s32 >> 6)) + s35 = s19 + s28 + (((s20 << 63) | (s20 >> 1))^((s20 << 56) | (s20 >> 8))^(s20 >> 7)) + (((s33 << 45) | (s33 >> 19))^((s33 << 3) | (s33 >> 61))^(s33 >> 6)) + s36 = s20 + s29 + (((s21 << 63) | (s21 >> 1))^((s21 << 56) | (s21 >> 8))^(s21 >> 7)) + (((s34 << 45) | (s34 >> 19))^((s34 << 3) | (s34 >> 61))^(s34 >> 6)) + s37 = s21 + s30 + (((s22 << 63) | (s22 >> 1))^((s22 << 56) | (s22 >> 8))^(s22 >> 7)) + (((s35 << 45) | (s35 >> 19))^((s35 << 3) | (s35 >> 61))^(s35 >> 6)) + s38 = s22 + s31 + (((s23 << 63) | (s23 >> 1))^((s23 << 56) | (s23 >> 8))^(s23 >> 7)) + (((s36 << 45) | (s36 >> 19))^((s36 << 3) | (s36 >> 61))^(s36 >> 6)) + s39 = s23 + s32 + (((s24 << 63) | (s24 >> 1))^((s24 << 56) | (s24 >> 8))^(s24 >> 7)) + (((s37 << 45) | (s37 >> 19))^((s37 << 3) | (s37 >> 61))^(s37 >> 6)) + s40 = s24 + s33 + (((s25 << 63) | (s25 >> 1))^((s25 << 56) | (s25 >> 8))^(s25 >> 7)) + (((s38 << 45) | (s38 >> 19))^((s38 << 3) | (s38 >> 61))^(s38 >> 6)) + s41 = s25 + s34 + (((s26 << 63) | (s26 >> 1))^((s26 << 56) | (s26 >> 8))^(s26 >> 7)) + (((s39 << 45) | (s39 >> 19))^((s39 << 3) | (s39 >> 61))^(s39 >> 6)) + s42 = s26 + s35 + (((s27 << 63) | (s27 >> 1))^((s27 << 56) | (s27 >> 8))^(s27 >> 7)) + (((s40 << 45) | (s40 >> 19))^((s40 << 3) | (s40 >> 61))^(s40 >> 6)) + s43 = s27 + s36 + (((s28 << 63) | (s28 >> 1))^((s28 << 56) | (s28 >> 8))^(s28 >> 7)) + (((s41 << 45) | (s41 >> 19))^((s41 << 3) | (s41 >> 61))^(s41 >> 6)) + s44 = s28 + s37 + (((s29 << 63) | (s29 >> 1))^((s29 << 56) | (s29 >> 8))^(s29 >> 7)) + (((s42 << 45) | (s42 >> 19))^((s42 << 3) | (s42 >> 61))^(s42 >> 6)) + s45 = s29 + s38 + (((s30 << 63) | (s30 >> 1))^((s30 << 56) | (s30 >> 8))^(s30 >> 7)) + (((s43 << 45) | (s43 >> 19))^((s43 << 3) | (s43 >> 61))^(s43 >> 6)) + s46 = s30 + s39 + (((s31 << 63) | (s31 >> 1))^((s31 << 56) | (s31 >> 8))^(s31 >> 7)) + (((s44 << 45) | (s44 >> 19))^((s44 << 3) | (s44 >> 61))^(s44 >> 6)) + s47 = s31 + s40 + (((s32 << 63) | (s32 >> 1))^((s32 << 56) | (s32 >> 8))^(s32 >> 7)) + (((s45 << 45) | (s45 >> 19))^((s45 << 3) | (s45 >> 61))^(s45 >> 6)) + s48 = s32 + s41 + (((s33 << 63) | (s33 >> 1))^((s33 << 56) | (s33 >> 8))^(s33 >> 7)) + (((s46 << 45) | (s46 >> 19))^((s46 << 3) | (s46 >> 61))^(s46 >> 6)) + s49 = s33 + s42 + (((s34 << 63) | (s34 >> 1))^((s34 << 56) | (s34 >> 8))^(s34 >> 7)) + (((s47 << 45) | (s47 >> 19))^((s47 << 3) | (s47 >> 61))^(s47 >> 6)) + s50 = s34 + s43 + (((s35 << 63) | (s35 >> 1))^((s35 << 56) | (s35 >> 8))^(s35 >> 7)) + (((s48 << 45) | (s48 >> 19))^((s48 << 3) | (s48 >> 61))^(s48 >> 6)) + s51 = s35 + s44 + (((s36 << 63) | (s36 >> 1))^((s36 << 56) | (s36 >> 8))^(s36 >> 7)) + (((s49 << 45) | (s49 >> 19))^((s49 << 3) | (s49 >> 61))^(s49 >> 6)) + s52 = s36 + s45 + (((s37 << 63) | (s37 >> 1))^((s37 << 56) | (s37 >> 8))^(s37 >> 7)) + (((s50 << 45) | (s50 >> 19))^((s50 << 3) | (s50 >> 61))^(s50 >> 6)) + s53 = s37 + s46 + (((s38 << 63) | (s38 >> 1))^((s38 << 56) | (s38 >> 8))^(s38 >> 7)) + (((s51 << 45) | (s51 >> 19))^((s51 << 3) | (s51 >> 61))^(s51 >> 6)) + s54 = s38 + s47 + (((s39 << 63) | (s39 >> 1))^((s39 << 56) | (s39 >> 8))^(s39 >> 7)) + (((s52 << 45) | (s52 >> 19))^((s52 << 3) | (s52 >> 61))^(s52 >> 6)) + s55 = s39 + s48 + (((s40 << 63) | (s40 >> 1))^((s40 << 56) | (s40 >> 8))^(s40 >> 7)) + (((s53 << 45) | (s53 >> 19))^((s53 << 3) | (s53 >> 61))^(s53 >> 6)) + s56 = s40 + s49 + (((s41 << 63) | (s41 >> 1))^((s41 << 56) | (s41 >> 8))^(s41 >> 7)) + (((s54 << 45) | (s54 >> 19))^((s54 << 3) | (s54 >> 61))^(s54 >> 6)) + s57 = s41 + s50 + (((s42 << 63) | (s42 >> 1))^((s42 << 56) | (s42 >> 8))^(s42 >> 7)) + (((s55 << 45) | (s55 >> 19))^((s55 << 3) | (s55 >> 61))^(s55 >> 6)) + s58 = s42 + s51 + (((s43 << 63) | (s43 >> 1))^((s43 << 56) | (s43 >> 8))^(s43 >> 7)) + (((s56 << 45) | (s56 >> 19))^((s56 << 3) | (s56 >> 61))^(s56 >> 6)) + s59 = s43 + s52 + (((s44 << 63) | (s44 >> 1))^((s44 << 56) | (s44 >> 8))^(s44 >> 7)) + (((s57 << 45) | (s57 >> 19))^((s57 << 3) | (s57 >> 61))^(s57 >> 6)) + s60 = s44 + s53 + (((s45 << 63) | (s45 >> 1))^((s45 << 56) | (s45 >> 8))^(s45 >> 7)) + (((s58 << 45) | (s58 >> 19))^((s58 << 3) | (s58 >> 61))^(s58 >> 6)) + s61 = s45 + s54 + (((s46 << 63) | (s46 >> 1))^((s46 << 56) | (s46 >> 8))^(s46 >> 7)) + (((s59 << 45) | (s59 >> 19))^((s59 << 3) | (s59 >> 61))^(s59 >> 6)) + s62 = s46 + s55 + (((s47 << 63) | (s47 >> 1))^((s47 << 56) | (s47 >> 8))^(s47 >> 7)) + (((s60 << 45) | (s60 >> 19))^((s60 << 3) | (s60 >> 61))^(s60 >> 6)) + s63 = s47 + s56 + (((s48 << 63) | (s48 >> 1))^((s48 << 56) | (s48 >> 8))^(s48 >> 7)) + (((s61 << 45) | (s61 >> 19))^((s61 << 3) | (s61 >> 61))^(s61 >> 6)) + s64 = s48 + s57 + (((s49 << 63) | (s49 >> 1))^((s49 << 56) | (s49 >> 8))^(s49 >> 7)) + (((s62 << 45) | (s62 >> 19))^((s62 << 3) | (s62 >> 61))^(s62 >> 6)) + s65 = s49 + s58 + (((s50 << 63) | (s50 >> 1))^((s50 << 56) | (s50 >> 8))^(s50 >> 7)) + (((s63 << 45) | (s63 >> 19))^((s63 << 3) | (s63 >> 61))^(s63 >> 6)) + s66 = s50 + s59 + (((s51 << 63) | (s51 >> 1))^((s51 << 56) | (s51 >> 8))^(s51 >> 7)) + (((s64 << 45) | (s64 >> 19))^((s64 << 3) | (s64 >> 61))^(s64 >> 6)) + s67 = s51 + s60 + (((s52 << 63) | (s52 >> 1))^((s52 << 56) | (s52 >> 8))^(s52 >> 7)) + (((s65 << 45) | (s65 >> 19))^((s65 << 3) | (s65 >> 61))^(s65 >> 6)) + s68 = s52 + s61 + (((s53 << 63) | (s53 >> 1))^((s53 << 56) | (s53 >> 8))^(s53 >> 7)) + (((s66 << 45) | (s66 >> 19))^((s66 << 3) | (s66 >> 61))^(s66 >> 6)) + s69 = s53 + s62 + (((s54 << 63) | (s54 >> 1))^((s54 << 56) | (s54 >> 8))^(s54 >> 7)) + (((s67 << 45) | (s67 >> 19))^((s67 << 3) | (s67 >> 61))^(s67 >> 6)) + s70 = s54 + s63 + (((s55 << 63) | (s55 >> 1))^((s55 << 56) | (s55 >> 8))^(s55 >> 7)) + (((s68 << 45) | (s68 >> 19))^((s68 << 3) | (s68 >> 61))^(s68 >> 6)) + s71 = s55 + s64 + (((s56 << 63) | (s56 >> 1))^((s56 << 56) | (s56 >> 8))^(s56 >> 7)) + (((s69 << 45) | (s69 >> 19))^((s69 << 3) | (s69 >> 61))^(s69 >> 6)) + s72 = s56 + s65 + (((s57 << 63) | (s57 >> 1))^((s57 << 56) | (s57 >> 8))^(s57 >> 7)) + (((s70 << 45) | (s70 >> 19))^((s70 << 3) | (s70 >> 61))^(s70 >> 6)) + s73 = s57 + s66 + (((s58 << 63) | (s58 >> 1))^((s58 << 56) | (s58 >> 8))^(s58 >> 7)) + (((s71 << 45) | (s71 >> 19))^((s71 << 3) | (s71 >> 61))^(s71 >> 6)) + s74 = s58 + s67 + (((s59 << 63) | (s59 >> 1))^((s59 << 56) | (s59 >> 8))^(s59 >> 7)) + (((s72 << 45) | (s72 >> 19))^((s72 << 3) | (s72 >> 61))^(s72 >> 6)) + s75 = s59 + s68 + (((s60 << 63) | (s60 >> 1))^((s60 << 56) | (s60 >> 8))^(s60 >> 7)) + (((s73 << 45) | (s73 >> 19))^((s73 << 3) | (s73 >> 61))^(s73 >> 6)) + s76 = s60 + s69 + (((s61 << 63) | (s61 >> 1))^((s61 << 56) | (s61 >> 8))^(s61 >> 7)) + (((s74 << 45) | (s74 >> 19))^((s74 << 3) | (s74 >> 61))^(s74 >> 6)) + s77 = s61 + s70 + (((s62 << 63) | (s62 >> 1))^((s62 << 56) | (s62 >> 8))^(s62 >> 7)) + (((s75 << 45) | (s75 >> 19))^((s75 << 3) | (s75 >> 61))^(s75 >> 6)) + s78 = s62 + s71 + (((s63 << 63) | (s63 >> 1))^((s63 << 56) | (s63 >> 8))^(s63 >> 7)) + (((s76 << 45) | (s76 >> 19))^((s76 << 3) | (s76 >> 61))^(s76 >> 6)) + s79 = s63 + s72 + (((s64 << 63) | (s64 >> 1))^((s64 << 56) | (s64 >> 8))^(s64 >> 7)) + (((s77 << 45) | (s77 >> 19))^((s77 << 3) | (s77 >> 61))^(s77 >> 6)) + + + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0x428a2f98d728ae22ul + s00 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0x7137449123ef65cdul + s01 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0xb5c0fbcfec4d3b2ful + s02 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0xe9b5dba58189dbbcul + s03 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0x3956c25bf348b538ul + s04 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0x59f111f1b605d019ul + s05 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0x923f82a4af194f9bul + s06 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0xab1c5ed5da6d8118ul + s07 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0xd807aa98a3030242ul + s08 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0x12835b0145706fbeul + s09 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0x243185be4ee4b28cul + s10 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0x550c7dc3d5ffb4e2ul + s11 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0x72be5d74f27b896ful + s12 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0x80deb1fe3b1696b1ul + s13 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0x9bdc06a725c71235ul + s14 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0xc19bf174cf692694ul + s15 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0xe49b69c19ef14ad2ul + s16 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0xefbe4786384f25e3ul + s17 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0x0fc19dc68b8cd5b5ul + s18 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0x240ca1cc77ac9c65ul + s19 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0x2de92c6f592b0275ul + s20 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0x4a7484aa6ea6e483ul + s21 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0x5cb0a9dcbd41fbd4ul + s22 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0x76f988da831153b5ul + s23 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0x983e5152ee66dfabul + s24 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0xa831c66d2db43210ul + s25 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0xb00327c898fb213ful + s26 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0xbf597fc7beef0ee4ul + s27 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0xc6e00bf33da88fc2ul + s28 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0xd5a79147930aa725ul + s29 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0x06ca6351e003826ful + s30 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0x142929670a0e6e70ul + s31 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0x27b70a8546d22ffcul + s32 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0x2e1b21385c26c926ul + s33 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0x4d2c6dfc5ac42aedul + s34 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0x53380d139d95b3dful + s35 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0x650a73548baf63deul + s36 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0x766a0abb3c77b2a8ul + s37 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0x81c2c92e47edaee6ul + s38 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0x92722c851482353bul + s39 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0xa2bfe8a14cf10364ul + s40 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0xa81a664bbc423001ul + s41 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0xc24b8b70d0f89791ul + s42 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0xc76c51a30654be30ul + s43 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0xd192e819d6ef5218ul + s44 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0xd69906245565a910ul + s45 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0xf40e35855771202aul + s46 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0x106aa07032bbd1b8ul + s47 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0x19a4c116b8d2d0c8ul + s48 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0x1e376c085141ab53ul + s49 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0x2748774cdf8eeb99ul + s50 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0x34b0bcb5e19b48a8ul + s51 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0x391c0cb3c5c95a63ul + s52 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0x4ed8aa4ae3418acbul + s53 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0x5b9cca4f7763e373ul + s54 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0x682e6ff3d6b2b8a3ul + s55 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0x748f82ee5defb2fcul + s56 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0x78a5636f43172f60ul + s57 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0x84c87814a1f0ab72ul + s58 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0x8cc702081a6439ecul + s59 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0x90befffa23631e28ul + s60 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0xa4506cebde82bde9ul + s61 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0xbef9a3f7b2c67915ul + s62 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0xc67178f2e372532bul + s63 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0xca273eceea26619cul + s64 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0xd186b8c721c0c207ul + s65 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0xeada7dd6cde0eb1eul + s66 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0xf57d4f7fee6ed178ul + s67 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0x06f067aa72176fbaul + s68 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0x0a637dc5a2c898a6ul + s69 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0x113f9804bef90daeul + s70 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0x1b710b35131c471bul + s71 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + h += (((e << 50) | (e >> 14)) ^ ((e << (64 - 18)) | (e >> 18)) ^ ((e << 23) | (e >> 41))) + (g ^ (e & (f ^ g))) + 0x28db77f523047d84ul + s72 + d += h; h += (((a << 36) | (a >> 28)) ^ ((a << (64 - 34)) | (a >> 34)) ^ ((a << 25) | (a >> 39))) + ((a & (b | c)) | (b & c)); + g += (((d << 50) | (d >> 14)) ^ ((d << (64 - 18)) | (d >> 18)) ^ ((d << 23) | (d >> 41))) + (f ^ (d & (e ^ f))) + 0x32caab7b40c72493ul + s73 + c += g; g += (((h << 36) | (h >> 28)) ^ ((h << (64 - 34)) | (h >> 34)) ^ ((h << 25) | (h >> 39))) + ((h & (a | b)) | (a & b)); + f += (((c << 50) | (c >> 14)) ^ ((c << (64 - 18)) | (c >> 18)) ^ ((c << 23) | (c >> 41))) + (e ^ (c & (d ^ e))) + 0x3c9ebe0a15c9bebcul + s74 + b += f; f += (((g << 36) | (g >> 28)) ^ ((g << (64 - 34)) | (g >> 34)) ^ ((g << 25) | (g >> 39))) + ((g & (h | a)) | (h & a)); + e += (((b << 50) | (b >> 14)) ^ ((b << (64 - 18)) | (b >> 18)) ^ ((b << 23) | (b >> 41))) + (d ^ (b & (c ^ d))) + 0x431d67c49c100d4cul + s75 + a += e; e += (((f << 36) | (f >> 28)) ^ ((f << (64 - 34)) | (f >> 34)) ^ ((f << 25) | (f >> 39))) + ((f & (g | h)) | (g & h)); + d += (((a << 50) | (a >> 14)) ^ ((a << (64 - 18)) | (a >> 18)) ^ ((a << 23) | (a >> 41))) + (c ^ (a & (b ^ c))) + 0x4cc5d4becb3e42b6ul + s76 + h += d; d += (((e << 36) | (e >> 28)) ^ ((e << (64 - 34)) | (e >> 34)) ^ ((e << 25) | (e >> 39))) + ((e & (f | g)) | (f & g)); + c += (((h << 50) | (h >> 14)) ^ ((h << (64 - 18)) | (h >> 18)) ^ ((h << 23) | (h >> 41))) + (b ^ (h & (a ^ b))) + 0x597f299cfc657e2aul + s77 + g += c; c += (((d << 36) | (d >> 28)) ^ ((d << (64 - 34)) | (d >> 34)) ^ ((d << 25) | (d >> 39))) + ((d & (e | f)) | (e & f)); + b += (((g << 50) | (g >> 14)) ^ ((g << (64 - 18)) | (g >> 18)) ^ ((g << 23) | (g >> 41))) + (a ^ (g & (h ^ a))) + 0x5fcb6fab3ad6faecul + s78 + f += b; b += (((c << 36) | (c >> 28)) ^ ((c << (64 - 34)) | (c >> 34)) ^ ((c << 25) | (c >> 39))) + ((c & (d | e)) | (d & e)); + a += (((f << 50) | (f >> 14)) ^ ((f << (64 - 18)) | (f >> 18)) ^ ((f << 23) | (f >> 41))) + (h ^ (f & (g ^ h))) + 0x6c44198c4a475817ul + s79 + e += a; a += (((b << 36) | (b >> 28)) ^ ((b << (64 - 34)) | (b >> 34)) ^ ((b << 25) | (b >> 39))) + ((b & (c | d)) | (c & d)); + + x[0] += a + x[1] += b + x[2] += c + x[3] += d + x[4] += e + x[5] += f + x[6] += g + x[7] += h +} + +const unpack = {b + var v : uint64 + + v = ((b[0] castto(uint64)) << 56) + v |= ((b[1] castto(uint64)) << 48) + v |= ((b[2] castto(uint64)) << 40) + v |= ((b[3] castto(uint64)) << 32) + v |= ((b[4] castto(uint64)) << 24) + v |= ((b[5] castto(uint64)) << 16) + v |= ((b[6] castto(uint64)) << 8) + v |= ((b[7] castto(uint64)) << 0) + -> v +} + +const pack = {out, v + out[0] = (v >> 56) castto(byte) + out[1] = (v >> 48) castto(byte) + out[2] = (v >> 40) castto(byte) + out[3] = (v >> 32) castto(byte) + out[4] = (v >> 24) castto(byte) + out[5] = (v >> 16) castto(byte) + out[6] = (v >> 8) castto(byte) + out[7] = (v >> 0) castto(byte) +} + diff --git a/lib/cryptohash/test/md5.myr b/lib/cryptohash/test/md5.myr new file mode 100644 index 0000000..42d1089 --- /dev/null +++ b/lib/cryptohash/test/md5.myr @@ -0,0 +1,18 @@ +use std +use cryptohash + +use "test/util.use" + +const main = { + hasheq(cryptohash.md5("")[:], \ + "d41d8cd98f00b204e9800998ecf8427e") + hasheq(cryptohash.md5("h")[:], \ + "2510c39011c5be704182423e3a695e91") + /* 64 byte block */ + hasheq(cryptohash.md5("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")[:], \ + "014842d480b571495a4a0363793f7367") + /* tail spanning */ + hasheq(cryptohash.md5("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb")[:], \ + "3b0bb4c5ece4a6568caa7266e740a140") +} + diff --git a/lib/cryptohash/test/sha1.myr b/lib/cryptohash/test/sha1.myr new file mode 100644 index 0000000..d2ccfb8 --- /dev/null +++ b/lib/cryptohash/test/sha1.myr @@ -0,0 +1,18 @@ +use std +use cryptohash + +use "test/util.use" + +const main = { + hasheq(cryptohash.sha1("")[:], \ + "da39a3ee5e6b4b0d3255bfef60951890d8af0709") + hasheq(cryptohash.sha1("h")[:], \ + "27d5482eebd075de44389774e2fc8c695cf48a75") + /* 64 byte block */ + hasheq(cryptohash.sha1("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")[:], \ + "0098ba824b5c16427bd7a1125a2a442aec25644d") + /* tail spanning */ + hasheq(cryptohash.sha1("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb")[:], \ + "4eb17e52bb55910b037869438f69d9c87643d75a") +} + diff --git a/lib/cryptohash/test/sha256.myr b/lib/cryptohash/test/sha256.myr new file mode 100644 index 0000000..e3981b4 --- /dev/null +++ b/lib/cryptohash/test/sha256.myr @@ -0,0 +1,29 @@ +use std +use cryptohash + +use "test/util.use" + +const main = { + hasheq(cryptohash.sha224("")[:], \ + "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f") + hasheq(cryptohash.sha224("h")[:], \ + "e0ccaeadfef916630c35576679e4cd4b438e7fc95a60b7361705f708") + /* 64 byte block */ + hasheq(cryptohash.sha224("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")[:], \ + "a88cd5cde6d6fe9136a4e58b49167461ea95d388ca2bdb7afdc3cbf4") + /* tail spanning */ + hasheq(cryptohash.sha224("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb")[:], \ + "4a5859b7efa22c3b25710520fc97b0a901f5cdba3e4f0becfeea725e") + + hasheq(cryptohash.sha256("")[:], \ + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + hasheq(cryptohash.sha256("h")[:], \ + "aaa9402664f1a41f40ebbc52c9993eb66aeb366602958fdfaa283b71e64db123") + /* 64 byte block */ + hasheq(cryptohash.sha256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")[:], \ + "ffe054fe7ae0cb6dc65c3af9b61d5209f439851db43d0ba5997337df154668eb") + /* tail spanning */ + hasheq(cryptohash.sha256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb")[:], \ + "bac8bf0f9794a520a5bf0ec64d3206edd1b9f2ef5ea118c9cad5365d84578de4") +} + diff --git a/lib/cryptohash/test/sha512.myr b/lib/cryptohash/test/sha512.myr new file mode 100644 index 0000000..f58f96e --- /dev/null +++ b/lib/cryptohash/test/sha512.myr @@ -0,0 +1,29 @@ +use std +use cryptohash + +use "test/util.use" + +const main = { + hasheq(cryptohash.sha384("")[:], \ + "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b") + hasheq(cryptohash.sha384("h")[:], \ + "a4eb0778c79fce94c02126543cba398d645b2fd4c6ff6a02eecc026bbe0cc0dd666279722b7615bc15b4c9126b941c04") + /* 64 byte block */ + hasheq(cryptohash.sha384("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")[:], \ + "2e404b9339da795776e510d96930b3be2904c500395b8cb7413334b82d4dec413b4b8113045a05bbbcff846f027423f6") + /* tail spanning */ + hasheq(cryptohash.sha384("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb")[:], \ + "f8f4b55a0fb1ac8506d2e5195c714a1ad16c3bf61ad8b2d544344b105a49a77ff3b8eb61e8f970a71864e9dad87042b1") + + hasheq(cryptohash.sha512("")[:], \ + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e") + hasheq(cryptohash.sha512("h")[:], \ + "2241bc8fc70705b42efead371fd4982c5ba69917e5b4b895810002644f0386da9c3131793458c2bf47608480d64a07278133c99912e0ba2daf23098f3520eb97") + /* 64 byte block */ + hasheq(cryptohash.sha512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")[:], \ + "01d35c10c6c38c2dcf48f7eebb3235fb5ad74a65ec4cd016e2354c637a8fb49b695ef3c1d6f7ae4cd74d78cc9c9bcac9d4f23a73019998a7f73038a5c9b2dbde") + /* tail spanning */ + hasheq(cryptohash.sha512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb")[:], \ + "d5c989d2e41299b6bfd57562b4b09cd2efa56f13c8fa109e0ce5ddbd6bfb5b34f8563608d6162104bef750023732581f22704d5df43feecbb05742be1d7c34fa") +} + diff --git a/lib/cryptohash/test/util.myr b/lib/cryptohash/test/util.myr new file mode 100644 index 0000000..ceb411c --- /dev/null +++ b/lib/cryptohash/test/util.myr @@ -0,0 +1,19 @@ +use std + +pkg = + const hasheq : (got : byte[:], expected : byte[:] -> void) +;; + +const hasheq = {got, expected + var sb, str + + sb = std.mksb() + for x in got + std.sbfmt(sb, "{p=0,w=2,x}", x) + ;; + str = std.sbfin(sb) + if (!std.sleq(str, expected)) + std.fatal("mismatched hashes:\n\tgot:\t{}\n\texpected:\t{}\n", str, expected) + ;; + std.slfree(str) +} diff --git a/lib/regex/bld.sub b/lib/regex/bld.sub new file mode 100644 index 0000000..0078d09 --- /dev/null +++ b/lib/regex/bld.sub @@ -0,0 +1,21 @@ +lib regex = + compile.myr + interp.myr + ranges.myr + types.myr + + lib ../std:std +;; + +bin redump {noinst} = + redump.myr + lib ../std:std + lib ../bio:bio + lib regex +;; + +gen ranges.myr {durable} = + mkchartab -a -p_ranges UnicodeData.txt -o ranges.myr +;; + +sub = test ;; diff --git a/lib/regex/compile.myr b/lib/regex/compile.myr new file mode 100644 index 0000000..28d7ce8 --- /dev/null +++ b/lib/regex/compile.myr @@ -0,0 +1,848 @@ +use std + +use "types.use" +use "ranges.use" + +pkg regex = + const parse : (re : byte[:] -> std.result(ast#, status)) + const compile : (re : byte[:] -> std.result(regex#, status)) + const dbgcompile : (re : byte[:] -> std.result(regex#, status)) + const free : (re : regex# -> void) + const failmsg : (st : status -> byte[:]) +;; + +type parseresult = union + `Some ast# + `None + `Fail status +;; + +/* Compiles a pattern into a regex */ +const compile = {pat + -> regexcompile(std.mk([.pat = pat, .nmatch = 1]), 0) +} + +const parse = {pat + var re + + re = std.mk([.pat = pat, .nmatch = 1]) + match regexparse(re) + | `None: -> `std.Fail `Incomplete + | `Fail f: -> `std.Fail f + | `Some t: + if re.pat.len > 0 + -> `std.Fail `Incomplete + else + -> `std.Ok t + ;; + ;; +} + +/* Compiles a pattern into a debug regex. This can be verbose. */ +const dbgcompile = {pat + var re + + re = std.mk([.pat = pat, .nmatch = 1, .debug = true]) + -> regexcompile(re, 0) +} + +/* compiles a pattern into an allocated regex */ +const regexcompile = {re, id + match regexparse(re) + | `None: -> `std.Fail (`Incomplete) + | `Fail f: -> `std.Fail f + | `Some t: + /* + we can stop early if we get + an incorrectly encoded char + */ + if re.pat.len > 0 + astfree(t) + -> `std.Fail (`Incomplete) + ;; + dump(re, t, 0) + append(re, `Ilbra 0) + gen(re, t) + append(re, `Irbra 0) + append(re, `Imatch id) + idump(re) + astfree(t) + -> `std.Ok re + ;; + -> `std.Fail (`Noimpl) +} + +const free = {re + /* all the threads should be dead, + so we shouldn't have to free any*/ + std.slfree(re.prog) + std.free(re) +} + + +/* generates bytecode from an AST */ +const gen = {re, t + match t# + |`Alt (a, b): genalt(re, a, b) + |`Cat (a, b): gen(re, a); gen(re, b) + /* repetition */ + |`Star a: genstar(re, a, false) + |`Rstar a: genstar(re, a, true) + |`Plus a: gen(re, a); genstar(re, a, false) + |`Rplus a: gen(re, a); genstar(re, a, true) + |`Quest a: genquest(re, a) + + /* end matches */ + |`Chr c: genchar(re, c) + |`Ranges sl: genranges(re, sl) + + /* meta */ + |`Bol: append(re, `Ibol) + |`Eol: append(re, `Ibol) + |`Bow: append(re, `Ibow) + |`Eow: append(re, `Ieow) + |`Cap (m, a): + append(re, `Ilbra m) + gen(re, a) + append(re, `Irbra m) + ;; + -> re.proglen +} + +const genranges = {re, sl + var lbuf : byte[4], hbuf : byte[4], boundbuf : byte[4] + var lsz, hsz, bsz, i + var rt : rangetrie# + + /* generate a trie of ranges */ + rt = std.zalloc() + for r in sl + /* + encode: + lo => bounds[loidx] - 1 + bounds[loidx] => bounds[loidx + 1] - 1 + ... + bounds[hiidx - 1] => hi + */ + lsz = std.encode(lbuf[:], r[0]) + hsz = std.encode(hbuf[:], r[1]) + for i = lsz; i < hsz; i++ + bsz = bound(boundbuf[:], i, 0xff) + rtinsert(rt, lbuf[:lsz], boundbuf[:bsz]) + lsz = bound(lbuf[:], i + 1, 0x00) + ;; + rtinsert(rt, lbuf[:lsz], hbuf[:hsz]) + ;; + if re.debug + rtdump(rt, 0) + ;; + rangegen(re, rt, rt.ranges, rt.link, rangeprogsize(rt) + re.proglen) + rtfree(rt) + -> re.proglen +} + +const bound = {buf, len, fill + var i, s + + if len == 1 + buf[0] = 0x7f + else + s = len castto(byte) + buf[0] = (0xff << (8 - s)) | (fill >> (s + 1)) + for i = 1; i < len; i++ + buf[i] = 0x80 | (fill >> 2) + ;; + ;; + -> len +} + +type rangetrie = struct + ranges : (byte, byte)[:] + link : rangetrie#[:] + end : bool +;; + +const rtdump = {rt, ind + var i + var l, h + + indent(ind) + std.put("Range (end = {}) {{\n", rt.end) + for i = 0; i < rt.ranges.len; i++ + indent(ind + 1) + (l, h) = rt.ranges[i] + std.put("0x{x}-0x{x}: \n", l, h) + rtdump(rt.link[i], ind + 1) + ;; + indent(ind) + std.put("}\n") +} + +const indent = {ind + var i + for i = 0; i < ind; i++ + std.put("\t") + ;; +} + +const rtinsert = {rt, lo, hi + var a, b + var n + + std.assert(lo.len == hi.len, "range sizes differ") + if lo.len == 0 + rt.end = true + -> + ;; + + n = rt.ranges.len + if n == 0 + rt.ranges = std.slpush(rt.ranges, (lo[0], hi[0])) + rt.link = std.slpush(rt.link, std.zalloc()) + else + /* + this is a safe way to compare because we know that ranges + should always be coming in ordered. This means that equal + values will be added one after the other. + */ + (a, b) = rt.ranges[n - 1] + if a != lo[0] || b != hi[0] + rt.ranges = std.slpush(rt.ranges, (lo[0], hi[0])) + rt.link = std.slpush(rt.link, std.zalloc()) + ;; + ;; + + rtinsert(rt.link[rt.link.len - 1], lo[1:], hi[1:]) +} + +const rtfree = {rt + for l in rt.link + rtfree(l) + ;; + std.slfree(rt.link) + std.slfree(rt.ranges) + std.free(rt) +} + +const rangegen = {re, rt, ranges, links, end + var alt, l0, l1, l2 + var a, b + var n + + n = ranges.len + if n == 0 + -> re.proglen + elif n == 1 + (a, b) = ranges[0] + append(re, `Irange (a, b)) + if links[0].end + if links[0].ranges.len > 0 + append(re, `Ifork (re.prog.len + 1, end)) + else + append(re, `Ijmp end) + ;; + ;; + rangegen(re, links[0], links[0].ranges, links[0].link, end) + else + alt = re.proglen + l0 = append(re, `Ifork (-1, -1)) + l1 = rangegen(re, rt, ranges[0:n/2], links[0:n/2], end) + l2 = rangegen(re, rt, ranges[n/2:n], links[n/2:n], end) + re.prog[alt] = `Ifork (l0, l1) + ;; + -> re.proglen +} + +const rangeprogsize = {rt + var sz + + if rt.ranges.len == 0 + sz = 0 + else + sz = 2*rt.ranges.len - 1 + for l in rt.link + sz += rangeprogsize(l) + ;; + ;; + if rt.end + sz += 1 + ;; + -> sz +} + +/* calculates the forward jump distance for a utf8 character range */ +const jmpdist = {n + var d + var i + + d = n - 1 + for i = n - 1; i > 0; i-- + d += i + ;; + -> d +} + +/* generates an alternation */ +const genalt = {re, l, r + var alt + var jmp + var l0 + var l1 + var l2 + + alt = re.proglen + l0 = append(re, `Ifork (-1, -1)) /* needs to be replaced */ + gen(re, l) + jmp = re.proglen + l1 = append(re, `Ijmp -1) /* needs to be replaced */ + l2 = gen(re, r) + + re.prog[alt] = `Ifork(l0, l1) + re.prog[jmp] = `Ijmp l2 + -> re.proglen +} + +/* generates a repetition operator */ +const genstar = {re, rep, reluct + var alt + var jmp + var l0 + var l1 + var l2 + + l0 = re.proglen + alt = re.proglen + l1 = append(re, `Ifork (-1, -1)) /* needs to be replaced */ + jmp = gen(re, rep) + l2 = append(re, `Ijmp -1) + + + /* reluctant matches should prefer jumping to the end. */ + if reluct + re.prog[alt] = `Ifork (l2, l1) + else + re.prog[alt] = `Ifork (l1, l2) + ;; + re.prog[jmp] = `Ijmp l0 + -> re.proglen +} + +/* generates a question mark operator */ +const genquest = {re, q + var alt + var l0 + var l1 + + alt = re.proglen + l0 = append(re, `Ifork (-1, -1)) /* needs to be replaced */ + l1 = gen(re, q) + re.prog[alt] = `Ifork (l0, l1) + -> re.proglen +} + +/* generates a single char match */ +const genchar = {re, c + var b : byte[4] + var n + var i + + n = std.encode(b[:], c) + std.assert(n > 0 && n < 4, "non-utf character in regex\n") + for i = 0; i < n; i++ + append(re, `Ibyte b[i]) + ;; + -> re.proglen +} + +/* appends an instructon to an re program */ +const append = {re, insn + if re.proglen == re.prog.len + re.prog = std.slgrow(re.prog, std.max(1, 2*re.proglen)) + ;; + re.prog[re.proglen] = insn + re.proglen++ + -> re.proglen +} + +/* instruction dump */ +const idump = {re + var i + + if !re.debug + -> + ;; + for i = 0; i < re.proglen; i++ + std.put("{}:\t", i) + match re.prog[i] + /* Char matching. Consume exactly one byte from the string. */ + | `Ibyte b: std.put("`Ibyte {} ({})\n", b, b castto(char)) + | `Irange (start, end): + std.put("`Irange ({},{})", start, end) + if std.isalnum(start castto(char)) && std.isalnum(end castto(char)) + std.put("\t/* {}-{} */", start castto(char), end castto(char)) + ;; + std.put("\n") + /* capture groups */ + | `Ilbra m: std.put("`Ilbra {}\n", m) + | `Irbra m: std.put("`Irbra {}\n", m) + /* anchors */ + | `Ibol: std.put("`Ibol\n") + | `Ieol: std.put("`Ieol\n") + | `Ibow: std.put("`Ibow\n") + | `Ieow: std.put("`Ieow\n") + /* control flow */ + | `Ifork (lip, rip): std.put("`Ifork ({},{})\n", lip, rip) + | `Ijmp ip: std.put("`Ijmp {}\n", ip) + | `Imatch id: std.put("`Imatch {}\n", id) + ;; + ;; +} + +/* AST dump */ +const dump = {re, t, indent + var i + + if !re.debug + -> + ;; + for i = 0; i < indent; i++ + std.put(" ") + ;; + match t# + | `Alt (a, b): + std.put("Alt\n") + dump(re, a, indent + 1) + dump(re, b, indent + 1) + | `Cat (a, b): + std.put("Cat\n") + dump(re, a, indent + 1) + dump(re, b, indent + 1) + /* repetition */ + | `Star a: + std.put("Star\n") + dump(re, a, indent + 1) + | `Rstar a: + std.put("Rstar\n") + dump(re, a, indent + 1) + | `Plus a: + std.put("Plus\n") + dump(re, a, indent + 1) + | `Rplus a: + std.put("Rplus\n") + dump(re, a, indent + 1) + | `Quest a: + std.put("Quest\n") + dump(re, a, indent + 1) + | `Bol: + std.put("Bol\n") + | `Eol: + std.put("Eol\n") + | `Bow: + std.put("Bow\n") + | `Eow: + std.put("Eow\n") + /* end matches */ + | `Chr c: + std.put("Char {}\n", c) + | `Ranges rl: + std.put("Ranges") + for r in rl + for i = 0; i < indent + 1; i++ + std.put(" ") + ;; + std.put("\t({}-{})\n", r[0], r[1]) + ;; + + /* meta */ + | `Cap (m, a): + std.put("Cap {}\n", m) + dump(re, a, indent + 1) + ;; +} + +/* parses an expression */ +const regexparse = {re + match altexpr(re) + | `Some t: + if re.pat.len == 0 + -> `Some t + else + astfree(t) + -> `Fail `Incomplete + ;; + | `None: + -> `None + | `Fail st: + -> `Fail st + ;; +} + +const altexpr = {re + var ret + + match catexpr(re) + | `Some t: + ret = t + if matchc(re, '|') + match altexpr(re) + | `Some rhs: + ret = mk(`Alt (ret, rhs)) + | `None: + astfree(ret) + -> `Fail (`Incomplete) + | `Fail f: + -> `Fail f + ;; + ;; + | other: + -> other + ;; + -> `Some ret +} + +const catexpr = {re + var ret + + match repexpr(re) + | `Some t: + ret = t + match catexpr(re) + | `Some rhs: + ret = mk(`Cat (t, rhs)) + | `Fail f: -> `Fail f + | `None: /* nothing */ + ;; + | other: + -> other + ;; + -> `Some ret +} + +const repexpr = {re + var ret + + match baseexpr(re) + | `Some t: + if matchc(re, '*') + if matchc(re, '?') + ret = mk(`Rstar t) + else + ret = mk(`Star t) + ;; + elif matchc(re, '+') + if matchc(re, '?') + ret = mk(`Rplus t) + else + ret = mk(`Plus t) + ;; + elif matchc(re, '?') + ret = mk(`Quest t) + else + ret = t + ;; + | other: + -> other + ;; + -> `Some ret +} + +const baseexpr = {re + var ret, m + + if re.pat.len == 0 + -> `None + ;; + match peekc(re) + /* lower prec operators */ + | '|': -> `None + | ')': -> `None + | '*': -> `Fail `Badrep + | '+': -> `Fail `Badrep + | '?': -> `Fail `Badrep + | '[': -> chrclass(re) + | '.': getc(re); ret = mk(`Ranges std.slpush([][:], [0, std.Maxcharval])) + | '^': getc(re); ret = mk(`Bol) + | '$': getc(re); ret = mk(`Eol) + | '(': + m = re.nmatch++ + getc(re) + match altexpr(re) + | `Some s: + if matchc(re, ')') + -> `Some mk(`Cap (m, s)) + else + -> `Fail `Unbalanced + ;; + | `None: -> `Fail `Emptyparen + | `Fail st: -> `Fail st + ;; + | '\\': + getc(re) /* consume the slash */ + if re.pat.len == 0 + -> `Fail `Incomplete + ;; + -> escaped(re) + | c: + getc(re) + ret = mk(`Chr c) + ;; + -> `Some ret +} + +const escaped = {re + var ret + + match getc(re) + /* character classes */ + | 'd': ret = `Some mk(`Ranges std.sldup(_ranges.tabasciidigit[:])) + | 'x': ret = `Some mk(`Ranges std.sldup(_ranges.tabasciixdigit[:])) + | 's': ret = `Some mk(`Ranges std.sldup(_ranges.tabasciispace[:])) + | 'w': ret = `Some mk(`Ranges std.sldup(_ranges.tabasciiword[:])) + | 'h': ret = `Some mk(`Ranges std.sldup(_ranges.tabasciiblank[:])) + + /* negated character classes */ + | 'W': ret = `Some mk(`Ranges negate(_ranges.tabasciiword[:])) + | 'S': ret = `Some mk(`Ranges negate(_ranges.tabasciispace[:])) + | 'D': ret = `Some mk(`Ranges negate(_ranges.tabasciidigit[:])) + | 'X': ret = `Some mk(`Ranges negate(_ranges.tabasciixdigit[:])) + | 'H': ret = `Some mk(`Ranges negate(_ranges.tabasciiblank[:])) + + /* unicode character classes */ + | 'p': ret = unicodeclass(re, false) + | 'P': ret = unicodeclass(re, true) + + /* operators that need an escape */ + | '<': ret = `Some mk(`Bow) + | '>': ret = `Some mk(`Eow) + + /* escaped metachars */ + | '^': ret = `Some mk(`Chr '^') + | '$': ret = `Some mk(`Chr '$') + | '.': ret = `Some mk(`Chr '.') + | '+': ret = `Some mk(`Chr '+') + | '?': ret = `Some mk(`Chr '?') + | chr: ret = `Fail `Badescape + ;; + -> ret +} + +const unicodeclass = {re, neg + var c, s + var tab + var t + var n + + if re.pat.len == 0 + -> `Fail (`Incomplete) + ;; + n = 0 + s = re.pat + /* either a single char pattern, or {pat} */ + match getc(re) + | '{': + s = s[1:] + while re.pat.len > 0 + c = getc(re) + if c == '}' + break + ;; + n += std.charlen(c) + ;; + | r: + n += std.charlen(r) + ;; + s = s[:n] + /* letters */ + if std.sleq(s, "L") || std.sleq(s, "Letter") + tab = _ranges.tabalpha[:] + elif std.sleq(s, "Lu") || std.sleq(s, "Uppercase_Letter") + tab = _ranges.tabupper[:] + elif std.sleq(s, "Ll") || std.sleq(s, "Lowercase_Letter") + tab = _ranges.tablower[:] + elif std.sleq(s, "Lt") || std.sleq(s, "Titlecase_Letter") + tab = _ranges.tablower[:] + /* numbers (incomplete) */ + elif std.sleq(s, "N") || std.sleq(s, "Number") + tab = _ranges.tabdigit[:] + elif std.sleq(s, "Z") || std.sleq(s, "Separator") + tab = _ranges.tabspace[:] + elif std.sleq(s, "Zs") || std.sleq(s, "Space_Separator") + tab = _ranges.tabblank[:] + else + -> `Fail (`Badrange) + ;; + if !neg + t = mk(`Ranges std.sldup(tab)) + else + t = mk(`Ranges negate(tab)) + ;; + -> `Some t +} + +const chrclass = {re + var rl, m, n + var neg + var t + + /* we know we saw '[' on entry */ + matchc(re, '[') + neg = false + if matchc(re, '^') + neg = true + ;; + rl = rangematch(re, [][:]) + while peekc(re) != ']' && re.pat.len > 0 + rl = rangematch(re, rl) + ;; + if !matchc(re, ']') + std.slfree(rl) + -> `Fail `Unbalanced + ;; + + std.sort(rl, {a, b; + if a[0] < b[0] + -> `std.Before + elif a[0] == b[0] + -> `std.Equal + else + -> `std.After + ;;}) + m = merge(rl) + std.slfree(rl) + if neg + n = negate(m) + std.slfree(m) + t = mk(`Ranges n) + else + t = mk(`Ranges m) + ;; + -> `Some t +} + +const rangematch = {re, sl + var lo + var hi + + lo = getc(re) + if matchc(re, '-') + hi = getc(re) + if lo <= hi + -> std.slpush(sl, [lo, hi]) + else + -> std.slpush(sl, [hi, lo]) + ;; + else + -> std.slpush(sl, [lo, lo]) + ;; +} + +const negate = {rng + var start, end, next + var neg + + neg = [][:] + start = 0 + next = 0 /* if we have no ranges */ + for r in rng + (end, next) = (r[0], r[1]) + neg = std.slpush(neg, [start, end - 1]) + start = next + 1 + ;; + neg = std.slpush(neg, [next + 1, std.Maxcharval]) + -> neg +} + +/* rl is a sorted list of ranges */ +const merge = {rl + var lo, hi + var ret + + if rl.len == 0 + -> [][:] + ;; + ret = [][:] + lo = rl[0][0] + hi = rl[0][1] + for r in rl[1:] + /* if it overlaps or abuts, merge */ + if r[0] <= hi + 1 + hi = r[1] + else + ret = std.slpush(ret, [lo, hi]) + lo = r[0] + hi = r[1] + ;; + ;; + -> std.slpush(ret, [lo, hi]) +} + + +const matchc = {re, c + var str + var chr + + (chr, str) = std.striter(re.pat) + if chr != c + -> false + ;; + re.pat = str + -> true +} + +const getc = {re + var c + + (c, re.pat) = std.striter(re.pat) + -> c +} + +const peekc = {re + var c + + (c, _) = std.striter(re.pat) + -> c +} + +const mk = {v + var t + + t = std.alloc() + t# = v + -> t +} + +const astfree = {t + match t# + | `Alt (a, b): astfree(a); astfree(b) + | `Cat (a, b): astfree(a); astfree(b) + /* repetition */ + | `Star a: astfree(a) + | `Rstar a: astfree(a) + | `Plus a: astfree(a) + | `Rplus a: astfree(a) + | `Quest a: astfree(a) + + /* end matches */ + | `Chr c: + | `Ranges rl: std.slfree(rl) + + /* meta */ + | `Cap (m, a): astfree(a) + | _: /* other types have no suballocations */ + ;; + std.free(t) +} + +const failmsg = {st + match st + | `Noimpl: -> "no implementation" + | `Incomplete: -> "regex ended before input fully parsed" + | `Unbalanced: -> "unbalanced bracket" + | `Emptyparen: -> "empty parentheses" + | `Badrep: -> "invalid repetition" + | `Badrange: -> "invalid range" + | `Badescape: -> "invalid escape code" + + ;; +} + diff --git a/lib/regex/configure b/lib/regex/configure new file mode 100755 index 0000000..37fe623 --- /dev/null +++ b/lib/regex/configure @@ -0,0 +1,52 @@ +#!/bin/sh + +prefix="/usr/local" + +for i in `seq 300`; do + echo "Lots of output to emulate automake... ok" + echo "Testing for things you'll never use... fail" + echo "Satisfying the fortran77 lobby... ok" + echo "Burning CPU time checking for the bloody obvious... ok" +done +echo "Automake emulated successfully" + +INST_ROOT='/usr/local' + +for arg in $*; do + shift 1 + case $arg in + "--prefix" | "-p") + prefix=shift $* + ;; + --prefix=*) + prefix=`echo $arg | sed 's/^--prefix=//g'` + ;; + "--help" | "-h") + echo "Usage:" + echo " --prefix | -p: The prefix to install to" + break; + ;; + *) echo "Unrecognized argument $arg";; + esac +done + +OS=`uname` + +echo export INST_ROOT=$prefix > config.mk +case $OS in + *Linux*) + echo 'export SYS=linux' >> config.mk + ;; + *Darwin*) + echo 'export SYS=osx' >> config.mk + ;; + *) + echo 'Unknown architecture.' + ;; +esac + +cat << EOF + Building with: + prefix=$prefix +EOF + diff --git a/lib/regex/doc/Makefile b/lib/regex/doc/Makefile new file mode 100644 index 0000000..c1749d3 --- /dev/null +++ b/lib/regex/doc/Makefile @@ -0,0 +1,5 @@ +MAN=myr-regex.3 \ + +include ../config.mk +include ../mk/myr.mk + diff --git a/lib/regex/doc/myr-regex.3 b/lib/regex/doc/myr-regex.3 new file mode 100644 index 0000000..c0d0da0 --- /dev/null +++ b/lib/regex/doc/myr-regex.3 @@ -0,0 +1,198 @@ +.TH MYR REGEX 1 +.SH NAME +regex myr-regex +.SH LIBRARY +regex +.SH SYNOPSIS +.B use regex +.I const compile : (re : byte[:] -> std.error(regex#, status)) +.I const dbgcompile : (re : byte[:] -> std.error(regex#, status)) +.I const free : (re : regex# -> void) +.br +.I const exec : (re : regex#, str : byte[:] -> bool) +.I const search : (re : regex#, str : byte[:] -> bool) +.SH DESCRIPTION +.PP +The regex library provides functions for compiling and evaluating regular +expressions, as described later in this document, or in myr-regex(7). +.PP +.I regex.compile will take a string describing a regex, and will attempt +to compile it, returing +.I `std.Success regex# +if the regex is valid, and there were no error conditions encountered during +compilation. If the compilation failed, +.I `std.Failure regex.status +will be returned, where regex.status is a failure code. + +.PP +.I regex.dbgcompile +is identical to +.I regex.compile, +however, it will print debugging information as it compiles, and each +time the regex is evaluated. + +.PP +.I regex.exec +will take the regex passed to it, and evaluate it over the text provided, +returning the +.I `std.Some matches, +or +.I `std.None +if there were no matches found. The matches must span the whole string. + +.PP +.I regex.search +is similar to regex.exec, but it will attempt to find a match somewhere +within the string, instead of attempting to find a match spanning the whole +string. + +.SH REGEX SYNTAX +.PP +The grammar used by libregex is below: + +.EX + regex : altexpr + altexpr : catexpr ('|' altexpr)+ + catexpr : repexpr (catexpr)+ + repexpr : baseexpr[*+?] + baseexpr : literal + | charclass + | charrange + | escaped + | '.' + | '^' + | '$' + | '(' regex ')' + charclass : see below + charrange : '[' (literal('-' literal)?)+']' +.EE + +The following metacharacters have the meanings listed below: +.TP +. +Matches a single unicode character +.TP +^ +Matches the beginning of a line. Does not consume any characters. +.TP +$ +Matches the end of a line. Does not consume any characters. +.TP +* +Matches any number of repetitions of the preceding regex fragment. +.TP +*? +Reluctantly matches any number of repetitions of the preceding regex fragment. +.TP ++ +Matches one or more repetitions of the preceding regex fragment. +.TP ++? +Reluctantly matches one or more repetitions of the preceding regex fragment. +.TP +? +Matches zero or one of the preceding regex fragment. + +.PP +In order to match a literal metacharacter, it needs to be preceded by +a '\\' character. + +The following character classes are supported: +.TP +\\d +ASCII digits +.TP +\\D +Negation of ASCII digits +.TP +\\x +ASCII Hex digits +.TP +\\X +Negation of ASCII Hex digits +.TP +\\s +ASCII spaces +.TP +\\S +Negation of ASCII spaces +.TP +\\w +ASCII word characters +.TP +\\W +Negation of ASCII word characters +.TP +\\h +ASCII whitespace characters +.TP +\\H +Negation of ASCII whitespace characters +.TP +\\pX, \\p{X} +Characters with unicode property 'X' +.TP +\\PX, \\P{X} +Negation of characters with unicode property 'X' + +.PP +Unicode properties that are supported are listed below: + +.TP +L, Letter +Unicode letter property +.TP +Lu, Uppercase_Letter +Uppercase letter unicode property +.TP +Ll, Lowercase_Letter +Lowercase letter unicode property +.TP +Lt, Titlecase_Letter +Titlecase letter unicode property +.TP +N, Number +Number unicode property +.TP +Z, Separator +Any separator character unicode property +.TP +Zs, Space_Separator +Space separator unicode property + + +.SH EXAMPLE +.EX + use std + use regex + + const main = { + match regex.compile(pat) + var i + | `std.Success re: + match regex.exec(re, text) + | `std.Some matches: + for i = 0; i < matches.len; i++ + std.put("Match %i: %s\n", i, match[i]) + ;; + | `std.None: std.put("Text did not match\n") + ;; + | `std.Failure err: + std.put("failed to compile regex") + ;; + } +.EE + +.SH FILES +The source code for this compiler is available from +.B git://git.eigenstate.org/git/ori/libregex.git + +.SH SEE ALSO +.IR mc(1) + +.SH BUGS +.PP +This code is insufficiently tested. + +.PP +This code does not support all of the regex features that one would expect. diff --git a/lib/regex/interp.myr b/lib/regex/interp.myr new file mode 100644 index 0000000..fc179c0 --- /dev/null +++ b/lib/regex/interp.myr @@ -0,0 +1,311 @@ +use std + +use "types.use" + +pkg regex = + const exec : (re : regex#, str : byte[:] -> std.option(byte[:][:])) + /* + FIXME: implement. This should scan for a possible start char in the + regex and use that to optimize. + const search : (re : regex#, str : byte[:] -> std.option(byte[:][:])) + */ +;; + +/* Ugly: for performance. std.option() should be used instead when unions get faster. */ +const Zthr = 0 castto(rethread#) + +const exec = {re, str + var thr + var m + + re.str = str + re.strp = 0 + thr = run(re) + if thr != Zthr + m = getmatches(re, thr) + cleanup(re) + -> `std.Some m + else + cleanup(re) + -> `std.None + ;; +} + +const cleanup = {re + var thr, next + + for thr = re.runq; thr != Zthr; thr = next + next = thr.next + thrfree(re, thr) + ;; + for thr = re.expired; thr != Zthr; thr = next + next = thr.next + thrfree(re, thr) + ;; +} + +const getmatches = {re, thr + var ret + var i + + ret = std.slalloc(re.nmatch) + for i = 0; i < re.nmatch; i++ + if thr.mstart[i] != -1 && thr.mend[i] != -1 + ret[i] = re.str[thr.mstart[i]:thr.mend[i]] + else + ret[i] = [][:] + ;; + ;; + -> ret +} + + +/* returns a matching thread, or Zthr if no threads matched */ +const run = {re + var i, ip + var consumed + var thr + var states + + states = std.mkbs() + re.runq = mkthread(re, 0) + re.runq.mstart = std.slalloc(re.nmatch) + re.runq.mend = std.slalloc(re.nmatch) + for i = 0; i < re.nmatch; i++ + re.runq.mstart[i] = -1 + re.runq.mend[i] = -1 + ;; + while re.nthr > 0 + while re.runq != Zthr + /* set up the next thread */ + thr = re.runq + re.runq = thr.next + + trace(re, thr, "\nrunning tid={}, ip={}, s[{}]={}\n", thr.tid, thr.ip, re.strp, std.decode(re.str[re.strp:])) + ip = thr.ip + consumed = step(re, thr, -1) + while !consumed + consumed = step(re, thr, ip) + ;; + + if std.bshas(states, thr.ip) + die(re, thr, "there can be only one") + ;; + + if thr.dead + thrfree(re, thr) + elif thr.matched && re.strp == re.str.len + -> thr + elif !thr.matched + std.bsput(states, thr.ip) + if re.expired == Zthr + re.expired = thr + ;; + if re.expiredtail != Zthr + re.expiredtail.next = thr + ;; + re.expiredtail = thr + thr.next = Zthr + + ;; + ;; + std.bsclear(states) + trace(re, thr, "switch\n") + re.runq = re.expired + re.expired = Zthr + re.expiredtail = Zthr + re.strp++ + ;; + -> Zthr +} + +/* + Steps forward one instruction. Returns true if a byte of input was + consumed, false otherwise. +*/ +const step = {re, thr, curip + var str + var mstart + var mend + + str = re.str + match re.prog[thr.ip] + /* Char matching. Consume exactly one byte from the string. */ + | `Ibyte b: + trace(re, thr, "\t{}:\tByte {} ({})\n", thr.ip, b, b castto(char)) + if !within(re, str) + die(re, thr, "end of string") + elif b != str[re.strp] + die(re, thr, "not right char") + else + thr.ip++ + trace(re, thr, "\t\tmatched {} with {}\n", b, str[re.strp]) + ;; + | `Irange (start, end): + trace(re, thr, "\t{}:\tRange ({}, {}) /* {} - {} */\n", thr.ip, start, end, start castto(char), end castto(char)) + if !within(re, str) || start > str[re.strp] || end < str[re.strp] + die(re, thr, "bad range") + else + thr.ip++ + ;; + /* + Non-consuming. All of these return false, and expect step to be + called again until exactly one byte is consumed from the string. + */ + | `Ibol: + trace(re, thr, "\t{}:\tBol\n", thr.ip) + if re.strp == 0 || str[re.strp - 1] == '\n' castto(byte) + thr.ip++ + -> false + else + die(re, thr, "not beginning of line") + ;; + | `Ieol: + trace(re, thr, "\t{}:\tEol\n", thr.ip) + if re.strp == str.len || str[re.strp] == '\n' castto(byte) + thr.ip++ + -> false + else + die(re, thr, "not end of line") + ;; + /* check for word characters */ + | `Ibow: + trace(re, thr, "\t{}:\tBow\n", thr.ip) + if iswordchar(str[re.strp:]) && (re.strp == 0 || !iswordchar(prevchar(str, re.strp))) + thr.ip++ + -> false + else + die(re, thr, "not beginning of word") + ;; + | `Ieow: + trace(re, thr, "\t{}:\tEow\n", thr.ip) + if re.strp == str.len && iswordchar(prevchar(str, re.strp)) + thr.ip++ + -> false + elif re.strp > 0 && !iswordchar(str[re.strp:]) && iswordchar(prevchar(str, re.strp)) + thr.ip++ + -> false + else + die(re, thr, "not end of word") + ;; + | `Ilbra m: + trace(re, thr, "\t{}:\tLbra {}\n", thr.ip, m) + trace(re, thr, "\t\tmatch start = {}\n", re.strp) + thr.mstart[m] = re.strp + thr.ip++ + -> false + | `Irbra m: + trace(re, thr, "\t{}:\tRbra {}\n", thr.ip, m) + thr.mend[m] = re.strp + thr.ip++ + -> false + | `Ifork (lip, rip): + trace(re, thr, "\t{}:\tFork ({}, {})\n", thr.ip, lip, rip) + mstart = std.sldup(thr.mstart) + mend = std.sldup(thr.mend) + fork(re, thr, rip, curip, mstart, mend) + thr.ip = lip + -> false + | `Ijmp ip: + trace(re, thr, "\t{}:\tJmp {}\n", thr.ip, ip) + thr.ip = ip + -> false + | `Imatch id: + trace(re, thr, "\t{}:\tMatch\n", thr.ip) + finish(re, thr) + -> true + ;; + -> true +} + +const fork = {re, thr, ip, curip, mstart, mend + var thr + + if ip == curip /* loop detection */ + -> + ;; + thr = mkthread(re, ip) + thr.next = re.runq + thr.mstart = mstart + thr.mend = mend + re.runq = thr +} + +const die = {re, thr, msg + /* + we can have die called on a thread + multiple times, eg, if it has a bad + range *and* end in a state that another + thread is in. We should only decrement + the number of threads for that once. + */ + trace(re, thr, "\t\tdie {}: {}\n", thr.tid, msg) + if !thr.dead + re.nthr-- + ;; + thr.dead = true +} + +const finish = {re, thr + trace(re, thr, "finish {}\n", thr.tid) + thr.matched = true + re.nthr-- +} + +var nexttid = 0 +const mkthread = {re, ip + var thr : rethread# + + thr = std.alloc() + + thr.next = Zthr + + thr.ip = ip + thr.tid = nexttid++ + thr.dead = false + thr.matched = false + + thr.mstart = [][:] + thr.mend = [][:] + + re.nthr++ + + -> thr +} + +const thrfree = {re, thr + trace(re, thr, "\t\tcleanup {}\n", thr.tid) + std.slfree(thr.mstart) + std.slfree(thr.mend) + std.free(thr) +} + +const within = {re, str + -> re.strp < str.len +} + +const trace : (re : regex#, thr : rethread#, msg : byte[:], args : ... -> void) = {re, thr, msg, args + var ap + + if re.debug + ap = std.vastart(&args) + std.putv(msg, &ap) + ;; +} + +/* must be called with i >= 1 */ +const prevchar = {s, i + std.assert(i != 0, "prevchar must be called with i >= 1\n") + i-- + while i != 0 && s[i] >= 0x80 + i-- + ;; + -> s[i:] +} + +const iswordchar = {s + var c + + c = std.decode(s) + -> std.isalpha(c) || std.isdigit(c) || c == '_' +} diff --git a/lib/regex/ranges.myr b/lib/regex/ranges.myr new file mode 100644 index 0000000..3efae43 --- /dev/null +++ b/lib/regex/ranges.myr @@ -0,0 +1,2386 @@ +/* + This set of unicode tables was automatically generated + by the following command: + mkchartab -a -p_ranges UnicodeData.txt -o ranges.myr + editing it manually is probably a waste of time. +*/ + +pkg _ranges = + const tabasciialpha + const tabasciiupper + const tabasciilower + const tabasciiword + const tabasciidigit + const tabasciixdigit + const tabasciispace + const tabasciiblank + const tabalpha + const tabupper + const tablower + const tabtitle + const tabword + const tabdigit + const tabxdigit + const tabspace + const tabblank +;; +const tabasciialpha = [ + ['\u{41}','\u{5a}'], + ['\u{61}','\u{7a}'], +] + +const tabasciiupper = [ + ['\u{41}','\u{5a}'], +] + +const tabasciilower = [ + ['\u{61}','\u{7a}'], +] + +const tabasciiword = [ + ['\u{30}','\u{39}'], + ['\u{41}','\u{5a}'], + ['\u{5f}','\u{5f}'], + ['\u{61}','\u{7a}'], +] + +const tabasciidigit = [ + ['\u{30}','\u{39}'], +] + +const tabasciixdigit = [ + ['\u{30}','\u{39}'], + ['\u{41}','\u{46}'], + ['\u{61}','\u{66}'], +] + +const tabasciispace = [ + ['\u{9}','\u{d}'], + ['\u{20}','\u{20}'], +] + +const tabasciiblank = [ + ['\u{9}','\u{9}'], + ['\u{20}','\u{20}'], +] + +const tabalpha = [ + ['\u{41}','\u{5a}'], + ['\u{61}','\u{7a}'], + ['\u{aa}','\u{aa}'], + ['\u{b5}','\u{b5}'], + ['\u{ba}','\u{ba}'], + ['\u{c0}','\u{d6}'], + ['\u{d8}','\u{f6}'], + ['\u{f8}','\u{2c1}'], + ['\u{2c6}','\u{2d1}'], + ['\u{2e0}','\u{2e4}'], + ['\u{2ec}','\u{2ec}'], + ['\u{2ee}','\u{2ee}'], + ['\u{370}','\u{374}'], + ['\u{376}','\u{377}'], + ['\u{37a}','\u{37d}'], + ['\u{386}','\u{386}'], + ['\u{388}','\u{38a}'], + ['\u{38c}','\u{38c}'], + ['\u{38e}','\u{3a1}'], + ['\u{3a3}','\u{3f5}'], + ['\u{3f7}','\u{481}'], + ['\u{48a}','\u{527}'], + ['\u{531}','\u{556}'], + ['\u{559}','\u{559}'], + ['\u{561}','\u{587}'], + ['\u{5d0}','\u{5ea}'], + ['\u{5f0}','\u{5f2}'], + ['\u{620}','\u{64a}'], + ['\u{66e}','\u{66f}'], + ['\u{671}','\u{6d3}'], + ['\u{6d5}','\u{6d5}'], + ['\u{6e5}','\u{6e6}'], + ['\u{6ee}','\u{6ef}'], + ['\u{6fa}','\u{6fc}'], + ['\u{6ff}','\u{6ff}'], + ['\u{710}','\u{710}'], + ['\u{712}','\u{72f}'], + ['\u{74d}','\u{7a5}'], + ['\u{7b1}','\u{7b1}'], + ['\u{7ca}','\u{7ea}'], + ['\u{7f4}','\u{7f5}'], + ['\u{7fa}','\u{7fa}'], + ['\u{800}','\u{815}'], + ['\u{81a}','\u{81a}'], + ['\u{824}','\u{824}'], + ['\u{828}','\u{828}'], + ['\u{840}','\u{858}'], + ['\u{8a0}','\u{8a0}'], + ['\u{8a2}','\u{8ac}'], + ['\u{904}','\u{939}'], + ['\u{93d}','\u{93d}'], + ['\u{950}','\u{950}'], + ['\u{958}','\u{961}'], + ['\u{971}','\u{977}'], + ['\u{979}','\u{97f}'], + ['\u{985}','\u{98c}'], + ['\u{98f}','\u{990}'], + ['\u{993}','\u{9a8}'], + ['\u{9aa}','\u{9b0}'], + ['\u{9b2}','\u{9b2}'], + ['\u{9b6}','\u{9b9}'], + ['\u{9bd}','\u{9bd}'], + ['\u{9ce}','\u{9ce}'], + ['\u{9dc}','\u{9dd}'], + ['\u{9df}','\u{9e1}'], + ['\u{9f0}','\u{9f1}'], + ['\u{a05}','\u{a0a}'], + ['\u{a0f}','\u{a10}'], + ['\u{a13}','\u{a28}'], + ['\u{a2a}','\u{a30}'], + ['\u{a32}','\u{a33}'], + ['\u{a35}','\u{a36}'], + ['\u{a38}','\u{a39}'], + ['\u{a59}','\u{a5c}'], + ['\u{a5e}','\u{a5e}'], + ['\u{a72}','\u{a74}'], + ['\u{a85}','\u{a8d}'], + ['\u{a8f}','\u{a91}'], + ['\u{a93}','\u{aa8}'], + ['\u{aaa}','\u{ab0}'], + ['\u{ab2}','\u{ab3}'], + ['\u{ab5}','\u{ab9}'], + ['\u{abd}','\u{abd}'], + ['\u{ad0}','\u{ad0}'], + ['\u{ae0}','\u{ae1}'], + ['\u{b05}','\u{b0c}'], + ['\u{b0f}','\u{b10}'], + ['\u{b13}','\u{b28}'], + ['\u{b2a}','\u{b30}'], + ['\u{b32}','\u{b33}'], + ['\u{b35}','\u{b39}'], + ['\u{b3d}','\u{b3d}'], + ['\u{b5c}','\u{b5d}'], + ['\u{b5f}','\u{b61}'], + ['\u{b71}','\u{b71}'], + ['\u{b83}','\u{b83}'], + ['\u{b85}','\u{b8a}'], + ['\u{b8e}','\u{b90}'], + ['\u{b92}','\u{b95}'], + ['\u{b99}','\u{b9a}'], + ['\u{b9c}','\u{b9c}'], + ['\u{b9e}','\u{b9f}'], + ['\u{ba3}','\u{ba4}'], + ['\u{ba8}','\u{baa}'], + ['\u{bae}','\u{bb9}'], + ['\u{bd0}','\u{bd0}'], + ['\u{c05}','\u{c0c}'], + ['\u{c0e}','\u{c10}'], + ['\u{c12}','\u{c28}'], + ['\u{c2a}','\u{c33}'], + ['\u{c35}','\u{c39}'], + ['\u{c3d}','\u{c3d}'], + ['\u{c58}','\u{c59}'], + ['\u{c60}','\u{c61}'], + ['\u{c85}','\u{c8c}'], + ['\u{c8e}','\u{c90}'], + ['\u{c92}','\u{ca8}'], + ['\u{caa}','\u{cb3}'], + ['\u{cb5}','\u{cb9}'], + ['\u{cbd}','\u{cbd}'], + ['\u{cde}','\u{cde}'], + ['\u{ce0}','\u{ce1}'], + ['\u{cf1}','\u{cf2}'], + ['\u{d05}','\u{d0c}'], + ['\u{d0e}','\u{d10}'], + ['\u{d12}','\u{d3a}'], + ['\u{d3d}','\u{d3d}'], + ['\u{d4e}','\u{d4e}'], + ['\u{d60}','\u{d61}'], + ['\u{d7a}','\u{d7f}'], + ['\u{d85}','\u{d96}'], + ['\u{d9a}','\u{db1}'], + ['\u{db3}','\u{dbb}'], + ['\u{dbd}','\u{dbd}'], + ['\u{dc0}','\u{dc6}'], + ['\u{e01}','\u{e30}'], + ['\u{e32}','\u{e33}'], + ['\u{e40}','\u{e46}'], + ['\u{e81}','\u{e82}'], + ['\u{e84}','\u{e84}'], + ['\u{e87}','\u{e88}'], + ['\u{e8a}','\u{e8a}'], + ['\u{e8d}','\u{e8d}'], + ['\u{e94}','\u{e97}'], + ['\u{e99}','\u{e9f}'], + ['\u{ea1}','\u{ea3}'], + ['\u{ea5}','\u{ea5}'], + ['\u{ea7}','\u{ea7}'], + ['\u{eaa}','\u{eab}'], + ['\u{ead}','\u{eb0}'], + ['\u{eb2}','\u{eb3}'], + ['\u{ebd}','\u{ebd}'], + ['\u{ec0}','\u{ec4}'], + ['\u{ec6}','\u{ec6}'], + ['\u{edc}','\u{edf}'], + ['\u{f00}','\u{f00}'], + ['\u{f40}','\u{f47}'], + ['\u{f49}','\u{f6c}'], + ['\u{f88}','\u{f8c}'], + ['\u{1000}','\u{102a}'], + ['\u{103f}','\u{103f}'], + ['\u{1050}','\u{1055}'], + ['\u{105a}','\u{105d}'], + ['\u{1061}','\u{1061}'], + ['\u{1065}','\u{1066}'], + ['\u{106e}','\u{1070}'], + ['\u{1075}','\u{1081}'], + ['\u{108e}','\u{108e}'], + ['\u{10a0}','\u{10c5}'], + ['\u{10c7}','\u{10c7}'], + ['\u{10cd}','\u{10cd}'], + ['\u{10d0}','\u{10fa}'], + ['\u{10fc}','\u{1248}'], + ['\u{124a}','\u{124d}'], + ['\u{1250}','\u{1256}'], + ['\u{1258}','\u{1258}'], + ['\u{125a}','\u{125d}'], + ['\u{1260}','\u{1288}'], + ['\u{128a}','\u{128d}'], + ['\u{1290}','\u{12b0}'], + ['\u{12b2}','\u{12b5}'], + ['\u{12b8}','\u{12be}'], + ['\u{12c0}','\u{12c0}'], + ['\u{12c2}','\u{12c5}'], + ['\u{12c8}','\u{12d6}'], + ['\u{12d8}','\u{1310}'], + ['\u{1312}','\u{1315}'], + ['\u{1318}','\u{135a}'], + ['\u{1380}','\u{138f}'], + ['\u{13a0}','\u{13f4}'], + ['\u{1401}','\u{166c}'], + ['\u{166f}','\u{167f}'], + ['\u{1681}','\u{169a}'], + ['\u{16a0}','\u{16ea}'], + ['\u{1700}','\u{170c}'], + ['\u{170e}','\u{1711}'], + ['\u{1720}','\u{1731}'], + ['\u{1740}','\u{1751}'], + ['\u{1760}','\u{176c}'], + ['\u{176e}','\u{1770}'], + ['\u{1780}','\u{17b3}'], + ['\u{17d7}','\u{17d7}'], + ['\u{17dc}','\u{17dc}'], + ['\u{1820}','\u{1877}'], + ['\u{1880}','\u{18a8}'], + ['\u{18aa}','\u{18aa}'], + ['\u{18b0}','\u{18f5}'], + ['\u{1900}','\u{191c}'], + ['\u{1950}','\u{196d}'], + ['\u{1970}','\u{1974}'], + ['\u{1980}','\u{19ab}'], + ['\u{19c1}','\u{19c7}'], + ['\u{1a00}','\u{1a16}'], + ['\u{1a20}','\u{1a54}'], + ['\u{1aa7}','\u{1aa7}'], + ['\u{1b05}','\u{1b33}'], + ['\u{1b45}','\u{1b4b}'], + ['\u{1b83}','\u{1ba0}'], + ['\u{1bae}','\u{1baf}'], + ['\u{1bba}','\u{1be5}'], + ['\u{1c00}','\u{1c23}'], + ['\u{1c4d}','\u{1c4f}'], + ['\u{1c5a}','\u{1c7d}'], + ['\u{1ce9}','\u{1cec}'], + ['\u{1cee}','\u{1cf1}'], + ['\u{1cf5}','\u{1cf6}'], + ['\u{1d00}','\u{1dbf}'], + ['\u{1e00}','\u{1f15}'], + ['\u{1f18}','\u{1f1d}'], + ['\u{1f20}','\u{1f45}'], + ['\u{1f48}','\u{1f4d}'], + ['\u{1f50}','\u{1f57}'], + ['\u{1f59}','\u{1f59}'], + ['\u{1f5b}','\u{1f5b}'], + ['\u{1f5d}','\u{1f5d}'], + ['\u{1f5f}','\u{1f7d}'], + ['\u{1f80}','\u{1fb4}'], + ['\u{1fb6}','\u{1fbc}'], + ['\u{1fbe}','\u{1fbe}'], + ['\u{1fc2}','\u{1fc4}'], + ['\u{1fc6}','\u{1fcc}'], + ['\u{1fd0}','\u{1fd3}'], + ['\u{1fd6}','\u{1fdb}'], + ['\u{1fe0}','\u{1fec}'], + ['\u{1ff2}','\u{1ff4}'], + ['\u{1ff6}','\u{1ffc}'], + ['\u{2071}','\u{2071}'], + ['\u{207f}','\u{207f}'], + ['\u{2090}','\u{209c}'], + ['\u{2102}','\u{2102}'], + ['\u{2107}','\u{2107}'], + ['\u{210a}','\u{2113}'], + ['\u{2115}','\u{2115}'], + ['\u{2119}','\u{211d}'], + ['\u{2124}','\u{2124}'], + ['\u{2126}','\u{2126}'], + ['\u{2128}','\u{2128}'], + ['\u{212a}','\u{212d}'], + ['\u{212f}','\u{2139}'], + ['\u{213c}','\u{213f}'], + ['\u{2145}','\u{2149}'], + ['\u{214e}','\u{214e}'], + ['\u{2183}','\u{2184}'], + ['\u{2c00}','\u{2c2e}'], + ['\u{2c30}','\u{2c5e}'], + ['\u{2c60}','\u{2ce4}'], + ['\u{2ceb}','\u{2cee}'], + ['\u{2cf2}','\u{2cf3}'], + ['\u{2d00}','\u{2d25}'], + ['\u{2d27}','\u{2d27}'], + ['\u{2d2d}','\u{2d2d}'], + ['\u{2d30}','\u{2d67}'], + ['\u{2d6f}','\u{2d6f}'], + ['\u{2d80}','\u{2d96}'], + ['\u{2da0}','\u{2da6}'], + ['\u{2da8}','\u{2dae}'], + ['\u{2db0}','\u{2db6}'], + ['\u{2db8}','\u{2dbe}'], + ['\u{2dc0}','\u{2dc6}'], + ['\u{2dc8}','\u{2dce}'], + ['\u{2dd0}','\u{2dd6}'], + ['\u{2dd8}','\u{2dde}'], + ['\u{2e2f}','\u{2e2f}'], + ['\u{3005}','\u{3006}'], + ['\u{3031}','\u{3035}'], + ['\u{303b}','\u{303c}'], + ['\u{3041}','\u{3096}'], + ['\u{309d}','\u{309f}'], + ['\u{30a1}','\u{30fa}'], + ['\u{30fc}','\u{30ff}'], + ['\u{3105}','\u{312d}'], + ['\u{3131}','\u{318e}'], + ['\u{31a0}','\u{31ba}'], + ['\u{31f0}','\u{31ff}'], + ['\u{3400}','\u{4db5}'], + ['\u{4e00}','\u{9fcc}'], + ['\u{a000}','\u{a48c}'], + ['\u{a4d0}','\u{a4fd}'], + ['\u{a500}','\u{a60c}'], + ['\u{a610}','\u{a61f}'], + ['\u{a62a}','\u{a62b}'], + ['\u{a640}','\u{a66e}'], + ['\u{a67f}','\u{a697}'], + ['\u{a6a0}','\u{a6e5}'], + ['\u{a717}','\u{a71f}'], + ['\u{a722}','\u{a788}'], + ['\u{a78b}','\u{a78e}'], + ['\u{a790}','\u{a793}'], + ['\u{a7a0}','\u{a7aa}'], + ['\u{a7f8}','\u{a801}'], + ['\u{a803}','\u{a805}'], + ['\u{a807}','\u{a80a}'], + ['\u{a80c}','\u{a822}'], + ['\u{a840}','\u{a873}'], + ['\u{a882}','\u{a8b3}'], + ['\u{a8f2}','\u{a8f7}'], + ['\u{a8fb}','\u{a8fb}'], + ['\u{a90a}','\u{a925}'], + ['\u{a930}','\u{a946}'], + ['\u{a960}','\u{a97c}'], + ['\u{a984}','\u{a9b2}'], + ['\u{a9cf}','\u{a9cf}'], + ['\u{aa00}','\u{aa28}'], + ['\u{aa40}','\u{aa42}'], + ['\u{aa44}','\u{aa4b}'], + ['\u{aa60}','\u{aa76}'], + ['\u{aa7a}','\u{aa7a}'], + ['\u{aa80}','\u{aaaf}'], + ['\u{aab1}','\u{aab1}'], + ['\u{aab5}','\u{aab6}'], + ['\u{aab9}','\u{aabd}'], + ['\u{aac0}','\u{aac0}'], + ['\u{aac2}','\u{aac2}'], + ['\u{aadb}','\u{aadd}'], + ['\u{aae0}','\u{aaea}'], + ['\u{aaf2}','\u{aaf4}'], + ['\u{ab01}','\u{ab06}'], + ['\u{ab09}','\u{ab0e}'], + ['\u{ab11}','\u{ab16}'], + ['\u{ab20}','\u{ab26}'], + ['\u{ab28}','\u{ab2e}'], + ['\u{abc0}','\u{abe2}'], + ['\u{ac00}','\u{d7a3}'], + ['\u{d7b0}','\u{d7c6}'], + ['\u{d7cb}','\u{d7fb}'], + ['\u{f900}','\u{fa6d}'], + ['\u{fa70}','\u{fad9}'], + ['\u{fb00}','\u{fb06}'], + ['\u{fb13}','\u{fb17}'], + ['\u{fb1d}','\u{fb1d}'], + ['\u{fb1f}','\u{fb28}'], + ['\u{fb2a}','\u{fb36}'], + ['\u{fb38}','\u{fb3c}'], + ['\u{fb3e}','\u{fb3e}'], + ['\u{fb40}','\u{fb41}'], + ['\u{fb43}','\u{fb44}'], + ['\u{fb46}','\u{fbb1}'], + ['\u{fbd3}','\u{fd3d}'], + ['\u{fd50}','\u{fd8f}'], + ['\u{fd92}','\u{fdc7}'], + ['\u{fdf0}','\u{fdfb}'], + ['\u{fe70}','\u{fe74}'], + ['\u{fe76}','\u{fefc}'], + ['\u{ff21}','\u{ff3a}'], + ['\u{ff41}','\u{ff5a}'], + ['\u{ff66}','\u{ffbe}'], + ['\u{ffc2}','\u{ffc7}'], + ['\u{ffca}','\u{ffcf}'], + ['\u{ffd2}','\u{ffd7}'], + ['\u{ffda}','\u{ffdc}'], + ['\u{10000}','\u{1000b}'], + ['\u{1000d}','\u{10026}'], + ['\u{10028}','\u{1003a}'], + ['\u{1003c}','\u{1003d}'], + ['\u{1003f}','\u{1004d}'], + ['\u{10050}','\u{1005d}'], + ['\u{10080}','\u{100fa}'], + ['\u{10280}','\u{1029c}'], + ['\u{102a0}','\u{102d0}'], + ['\u{10300}','\u{1031e}'], + ['\u{10330}','\u{10340}'], + ['\u{10342}','\u{10349}'], + ['\u{10380}','\u{1039d}'], + ['\u{103a0}','\u{103c3}'], + ['\u{103c8}','\u{103cf}'], + ['\u{10400}','\u{1049d}'], + ['\u{10800}','\u{10805}'], + ['\u{10808}','\u{10808}'], + ['\u{1080a}','\u{10835}'], + ['\u{10837}','\u{10838}'], + ['\u{1083c}','\u{1083c}'], + ['\u{1083f}','\u{10855}'], + ['\u{10900}','\u{10915}'], + ['\u{10920}','\u{10939}'], + ['\u{10980}','\u{109b7}'], + ['\u{109be}','\u{109bf}'], + ['\u{10a00}','\u{10a00}'], + ['\u{10a10}','\u{10a13}'], + ['\u{10a15}','\u{10a17}'], + ['\u{10a19}','\u{10a33}'], + ['\u{10a60}','\u{10a7c}'], + ['\u{10b00}','\u{10b35}'], + ['\u{10b40}','\u{10b55}'], + ['\u{10b60}','\u{10b72}'], + ['\u{10c00}','\u{10c48}'], + ['\u{11003}','\u{11037}'], + ['\u{11083}','\u{110af}'], + ['\u{110d0}','\u{110e8}'], + ['\u{11103}','\u{11126}'], + ['\u{11183}','\u{111b2}'], + ['\u{111c1}','\u{111c4}'], + ['\u{11680}','\u{116aa}'], + ['\u{12000}','\u{1236e}'], + ['\u{13000}','\u{1342e}'], + ['\u{16800}','\u{16a38}'], + ['\u{16f00}','\u{16f44}'], + ['\u{16f50}','\u{16f50}'], + ['\u{16f93}','\u{16f9f}'], + ['\u{1b000}','\u{1b001}'], + ['\u{1d400}','\u{1d454}'], + ['\u{1d456}','\u{1d49c}'], + ['\u{1d49e}','\u{1d49f}'], + ['\u{1d4a2}','\u{1d4a2}'], + ['\u{1d4a5}','\u{1d4a6}'], + ['\u{1d4a9}','\u{1d4ac}'], + ['\u{1d4ae}','\u{1d4b9}'], + ['\u{1d4bb}','\u{1d4bb}'], + ['\u{1d4bd}','\u{1d4c3}'], + ['\u{1d4c5}','\u{1d505}'], + ['\u{1d507}','\u{1d50a}'], + ['\u{1d50d}','\u{1d514}'], + ['\u{1d516}','\u{1d51c}'], + ['\u{1d51e}','\u{1d539}'], + ['\u{1d53b}','\u{1d53e}'], + ['\u{1d540}','\u{1d544}'], + ['\u{1d546}','\u{1d546}'], + ['\u{1d54a}','\u{1d550}'], + ['\u{1d552}','\u{1d6a5}'], + ['\u{1d6a8}','\u{1d6c0}'], + ['\u{1d6c2}','\u{1d6da}'], + ['\u{1d6dc}','\u{1d6fa}'], + ['\u{1d6fc}','\u{1d714}'], + ['\u{1d716}','\u{1d734}'], + ['\u{1d736}','\u{1d74e}'], + ['\u{1d750}','\u{1d76e}'], + ['\u{1d770}','\u{1d788}'], + ['\u{1d78a}','\u{1d7a8}'], + ['\u{1d7aa}','\u{1d7c2}'], + ['\u{1d7c4}','\u{1d7cb}'], + ['\u{1ee00}','\u{1ee03}'], + ['\u{1ee05}','\u{1ee1f}'], + ['\u{1ee21}','\u{1ee22}'], + ['\u{1ee24}','\u{1ee24}'], + ['\u{1ee27}','\u{1ee27}'], + ['\u{1ee29}','\u{1ee32}'], + ['\u{1ee34}','\u{1ee37}'], + ['\u{1ee39}','\u{1ee39}'], + ['\u{1ee3b}','\u{1ee3b}'], + ['\u{1ee42}','\u{1ee42}'], + ['\u{1ee47}','\u{1ee47}'], + ['\u{1ee49}','\u{1ee49}'], + ['\u{1ee4b}','\u{1ee4b}'], + ['\u{1ee4d}','\u{1ee4f}'], + ['\u{1ee51}','\u{1ee52}'], + ['\u{1ee54}','\u{1ee54}'], + ['\u{1ee57}','\u{1ee57}'], + ['\u{1ee59}','\u{1ee59}'], + ['\u{1ee5b}','\u{1ee5b}'], + ['\u{1ee5d}','\u{1ee5d}'], + ['\u{1ee5f}','\u{1ee5f}'], + ['\u{1ee61}','\u{1ee62}'], + ['\u{1ee64}','\u{1ee64}'], + ['\u{1ee67}','\u{1ee6a}'], + ['\u{1ee6c}','\u{1ee72}'], + ['\u{1ee74}','\u{1ee77}'], + ['\u{1ee79}','\u{1ee7c}'], + ['\u{1ee7e}','\u{1ee7e}'], + ['\u{1ee80}','\u{1ee89}'], + ['\u{1ee8b}','\u{1ee9b}'], + ['\u{1eea1}','\u{1eea3}'], + ['\u{1eea5}','\u{1eea9}'], + ['\u{1eeab}','\u{1eebb}'], + ['\u{20000}','\u{2a6d6}'], + ['\u{2a700}','\u{2b734}'], + ['\u{2b740}','\u{2b81d}'], + ['\u{2f800}','\u{2fa1d}'], +] + +const tabupper = [ + ['\u{41}','\u{5a}'], + ['\u{c0}','\u{d6}'], + ['\u{d8}','\u{de}'], + ['\u{100}','\u{100}'], + ['\u{102}','\u{102}'], + ['\u{104}','\u{104}'], + ['\u{106}','\u{106}'], + ['\u{108}','\u{108}'], + ['\u{10a}','\u{10a}'], + ['\u{10c}','\u{10c}'], + ['\u{10e}','\u{10e}'], + ['\u{110}','\u{110}'], + ['\u{112}','\u{112}'], + ['\u{114}','\u{114}'], + ['\u{116}','\u{116}'], + ['\u{118}','\u{118}'], + ['\u{11a}','\u{11a}'], + ['\u{11c}','\u{11c}'], + ['\u{11e}','\u{11e}'], + ['\u{120}','\u{120}'], + ['\u{122}','\u{122}'], + ['\u{124}','\u{124}'], + ['\u{126}','\u{126}'], + ['\u{128}','\u{128}'], + ['\u{12a}','\u{12a}'], + ['\u{12c}','\u{12c}'], + ['\u{12e}','\u{12e}'], + ['\u{130}','\u{130}'], + ['\u{132}','\u{132}'], + ['\u{134}','\u{134}'], + ['\u{136}','\u{136}'], + ['\u{139}','\u{139}'], + ['\u{13b}','\u{13b}'], + ['\u{13d}','\u{13d}'], + ['\u{13f}','\u{13f}'], + ['\u{141}','\u{141}'], + ['\u{143}','\u{143}'], + ['\u{145}','\u{145}'], + ['\u{147}','\u{147}'], + ['\u{14a}','\u{14a}'], + ['\u{14c}','\u{14c}'], + ['\u{14e}','\u{14e}'], + ['\u{150}','\u{150}'], + ['\u{152}','\u{152}'], + ['\u{154}','\u{154}'], + ['\u{156}','\u{156}'], + ['\u{158}','\u{158}'], + ['\u{15a}','\u{15a}'], + ['\u{15c}','\u{15c}'], + ['\u{15e}','\u{15e}'], + ['\u{160}','\u{160}'], + ['\u{162}','\u{162}'], + ['\u{164}','\u{164}'], + ['\u{166}','\u{166}'], + ['\u{168}','\u{168}'], + ['\u{16a}','\u{16a}'], + ['\u{16c}','\u{16c}'], + ['\u{16e}','\u{16e}'], + ['\u{170}','\u{170}'], + ['\u{172}','\u{172}'], + ['\u{174}','\u{174}'], + ['\u{176}','\u{176}'], + ['\u{178}','\u{179}'], + ['\u{17b}','\u{17b}'], + ['\u{17d}','\u{17d}'], + ['\u{181}','\u{182}'], + ['\u{184}','\u{184}'], + ['\u{186}','\u{187}'], + ['\u{189}','\u{18b}'], + ['\u{18e}','\u{191}'], + ['\u{193}','\u{194}'], + ['\u{196}','\u{198}'], + ['\u{19c}','\u{19d}'], + ['\u{19f}','\u{1a0}'], + ['\u{1a2}','\u{1a2}'], + ['\u{1a4}','\u{1a4}'], + ['\u{1a6}','\u{1a7}'], + ['\u{1a9}','\u{1a9}'], + ['\u{1ac}','\u{1ac}'], + ['\u{1ae}','\u{1af}'], + ['\u{1b1}','\u{1b3}'], + ['\u{1b5}','\u{1b5}'], + ['\u{1b7}','\u{1b8}'], + ['\u{1bc}','\u{1bc}'], + ['\u{1c4}','\u{1c4}'], + ['\u{1c7}','\u{1c7}'], + ['\u{1ca}','\u{1ca}'], + ['\u{1cd}','\u{1cd}'], + ['\u{1cf}','\u{1cf}'], + ['\u{1d1}','\u{1d1}'], + ['\u{1d3}','\u{1d3}'], + ['\u{1d5}','\u{1d5}'], + ['\u{1d7}','\u{1d7}'], + ['\u{1d9}','\u{1d9}'], + ['\u{1db}','\u{1db}'], + ['\u{1de}','\u{1de}'], + ['\u{1e0}','\u{1e0}'], + ['\u{1e2}','\u{1e2}'], + ['\u{1e4}','\u{1e4}'], + ['\u{1e6}','\u{1e6}'], + ['\u{1e8}','\u{1e8}'], + ['\u{1ea}','\u{1ea}'], + ['\u{1ec}','\u{1ec}'], + ['\u{1ee}','\u{1ee}'], + ['\u{1f1}','\u{1f1}'], + ['\u{1f4}','\u{1f4}'], + ['\u{1f6}','\u{1f8}'], + ['\u{1fa}','\u{1fa}'], + ['\u{1fc}','\u{1fc}'], + ['\u{1fe}','\u{1fe}'], + ['\u{200}','\u{200}'], + ['\u{202}','\u{202}'], + ['\u{204}','\u{204}'], + ['\u{206}','\u{206}'], + ['\u{208}','\u{208}'], + ['\u{20a}','\u{20a}'], + ['\u{20c}','\u{20c}'], + ['\u{20e}','\u{20e}'], + ['\u{210}','\u{210}'], + ['\u{212}','\u{212}'], + ['\u{214}','\u{214}'], + ['\u{216}','\u{216}'], + ['\u{218}','\u{218}'], + ['\u{21a}','\u{21a}'], + ['\u{21c}','\u{21c}'], + ['\u{21e}','\u{21e}'], + ['\u{220}','\u{220}'], + ['\u{222}','\u{222}'], + ['\u{224}','\u{224}'], + ['\u{226}','\u{226}'], + ['\u{228}','\u{228}'], + ['\u{22a}','\u{22a}'], + ['\u{22c}','\u{22c}'], + ['\u{22e}','\u{22e}'], + ['\u{230}','\u{230}'], + ['\u{232}','\u{232}'], + ['\u{23a}','\u{23b}'], + ['\u{23d}','\u{23e}'], + ['\u{241}','\u{241}'], + ['\u{243}','\u{246}'], + ['\u{248}','\u{248}'], + ['\u{24a}','\u{24a}'], + ['\u{24c}','\u{24c}'], + ['\u{24e}','\u{24e}'], + ['\u{370}','\u{370}'], + ['\u{372}','\u{372}'], + ['\u{376}','\u{376}'], + ['\u{386}','\u{386}'], + ['\u{388}','\u{38a}'], + ['\u{38c}','\u{38c}'], + ['\u{38e}','\u{38f}'], + ['\u{391}','\u{3a1}'], + ['\u{3a3}','\u{3ab}'], + ['\u{3cf}','\u{3cf}'], + ['\u{3d2}','\u{3d4}'], + ['\u{3d8}','\u{3d8}'], + ['\u{3da}','\u{3da}'], + ['\u{3dc}','\u{3dc}'], + ['\u{3de}','\u{3de}'], + ['\u{3e0}','\u{3e0}'], + ['\u{3e2}','\u{3e2}'], + ['\u{3e4}','\u{3e4}'], + ['\u{3e6}','\u{3e6}'], + ['\u{3e8}','\u{3e8}'], + ['\u{3ea}','\u{3ea}'], + ['\u{3ec}','\u{3ec}'], + ['\u{3ee}','\u{3ee}'], + ['\u{3f4}','\u{3f4}'], + ['\u{3f7}','\u{3f7}'], + ['\u{3f9}','\u{3fa}'], + ['\u{3fd}','\u{42f}'], + ['\u{460}','\u{460}'], + ['\u{462}','\u{462}'], + ['\u{464}','\u{464}'], + ['\u{466}','\u{466}'], + ['\u{468}','\u{468}'], + ['\u{46a}','\u{46a}'], + ['\u{46c}','\u{46c}'], + ['\u{46e}','\u{46e}'], + ['\u{470}','\u{470}'], + ['\u{472}','\u{472}'], + ['\u{474}','\u{474}'], + ['\u{476}','\u{476}'], + ['\u{478}','\u{478}'], + ['\u{47a}','\u{47a}'], + ['\u{47c}','\u{47c}'], + ['\u{47e}','\u{47e}'], + ['\u{480}','\u{480}'], + ['\u{48a}','\u{48a}'], + ['\u{48c}','\u{48c}'], + ['\u{48e}','\u{48e}'], + ['\u{490}','\u{490}'], + ['\u{492}','\u{492}'], + ['\u{494}','\u{494}'], + ['\u{496}','\u{496}'], + ['\u{498}','\u{498}'], + ['\u{49a}','\u{49a}'], + ['\u{49c}','\u{49c}'], + ['\u{49e}','\u{49e}'], + ['\u{4a0}','\u{4a0}'], + ['\u{4a2}','\u{4a2}'], + ['\u{4a4}','\u{4a4}'], + ['\u{4a6}','\u{4a6}'], + ['\u{4a8}','\u{4a8}'], + ['\u{4aa}','\u{4aa}'], + ['\u{4ac}','\u{4ac}'], + ['\u{4ae}','\u{4ae}'], + ['\u{4b0}','\u{4b0}'], + ['\u{4b2}','\u{4b2}'], + ['\u{4b4}','\u{4b4}'], + ['\u{4b6}','\u{4b6}'], + ['\u{4b8}','\u{4b8}'], + ['\u{4ba}','\u{4ba}'], + ['\u{4bc}','\u{4bc}'], + ['\u{4be}','\u{4be}'], + ['\u{4c0}','\u{4c1}'], + ['\u{4c3}','\u{4c3}'], + ['\u{4c5}','\u{4c5}'], + ['\u{4c7}','\u{4c7}'], + ['\u{4c9}','\u{4c9}'], + ['\u{4cb}','\u{4cb}'], + ['\u{4cd}','\u{4cd}'], + ['\u{4d0}','\u{4d0}'], + ['\u{4d2}','\u{4d2}'], + ['\u{4d4}','\u{4d4}'], + ['\u{4d6}','\u{4d6}'], + ['\u{4d8}','\u{4d8}'], + ['\u{4da}','\u{4da}'], + ['\u{4dc}','\u{4dc}'], + ['\u{4de}','\u{4de}'], + ['\u{4e0}','\u{4e0}'], + ['\u{4e2}','\u{4e2}'], + ['\u{4e4}','\u{4e4}'], + ['\u{4e6}','\u{4e6}'], + ['\u{4e8}','\u{4e8}'], + ['\u{4ea}','\u{4ea}'], + ['\u{4ec}','\u{4ec}'], + ['\u{4ee}','\u{4ee}'], + ['\u{4f0}','\u{4f0}'], + ['\u{4f2}','\u{4f2}'], + ['\u{4f4}','\u{4f4}'], + ['\u{4f6}','\u{4f6}'], + ['\u{4f8}','\u{4f8}'], + ['\u{4fa}','\u{4fa}'], + ['\u{4fc}','\u{4fc}'], + ['\u{4fe}','\u{4fe}'], + ['\u{500}','\u{500}'], + ['\u{502}','\u{502}'], + ['\u{504}','\u{504}'], + ['\u{506}','\u{506}'], + ['\u{508}','\u{508}'], + ['\u{50a}','\u{50a}'], + ['\u{50c}','\u{50c}'], + ['\u{50e}','\u{50e}'], + ['\u{510}','\u{510}'], + ['\u{512}','\u{512}'], + ['\u{514}','\u{514}'], + ['\u{516}','\u{516}'], + ['\u{518}','\u{518}'], + ['\u{51a}','\u{51a}'], + ['\u{51c}','\u{51c}'], + ['\u{51e}','\u{51e}'], + ['\u{520}','\u{520}'], + ['\u{522}','\u{522}'], + ['\u{524}','\u{524}'], + ['\u{526}','\u{526}'], + ['\u{531}','\u{556}'], + ['\u{10a0}','\u{10c5}'], + ['\u{10c7}','\u{10c7}'], + ['\u{10cd}','\u{10cd}'], + ['\u{1e00}','\u{1e00}'], + ['\u{1e02}','\u{1e02}'], + ['\u{1e04}','\u{1e04}'], + ['\u{1e06}','\u{1e06}'], + ['\u{1e08}','\u{1e08}'], + ['\u{1e0a}','\u{1e0a}'], + ['\u{1e0c}','\u{1e0c}'], + ['\u{1e0e}','\u{1e0e}'], + ['\u{1e10}','\u{1e10}'], + ['\u{1e12}','\u{1e12}'], + ['\u{1e14}','\u{1e14}'], + ['\u{1e16}','\u{1e16}'], + ['\u{1e18}','\u{1e18}'], + ['\u{1e1a}','\u{1e1a}'], + ['\u{1e1c}','\u{1e1c}'], + ['\u{1e1e}','\u{1e1e}'], + ['\u{1e20}','\u{1e20}'], + ['\u{1e22}','\u{1e22}'], + ['\u{1e24}','\u{1e24}'], + ['\u{1e26}','\u{1e26}'], + ['\u{1e28}','\u{1e28}'], + ['\u{1e2a}','\u{1e2a}'], + ['\u{1e2c}','\u{1e2c}'], + ['\u{1e2e}','\u{1e2e}'], + ['\u{1e30}','\u{1e30}'], + ['\u{1e32}','\u{1e32}'], + ['\u{1e34}','\u{1e34}'], + ['\u{1e36}','\u{1e36}'], + ['\u{1e38}','\u{1e38}'], + ['\u{1e3a}','\u{1e3a}'], + ['\u{1e3c}','\u{1e3c}'], + ['\u{1e3e}','\u{1e3e}'], + ['\u{1e40}','\u{1e40}'], + ['\u{1e42}','\u{1e42}'], + ['\u{1e44}','\u{1e44}'], + ['\u{1e46}','\u{1e46}'], + ['\u{1e48}','\u{1e48}'], + ['\u{1e4a}','\u{1e4a}'], + ['\u{1e4c}','\u{1e4c}'], + ['\u{1e4e}','\u{1e4e}'], + ['\u{1e50}','\u{1e50}'], + ['\u{1e52}','\u{1e52}'], + ['\u{1e54}','\u{1e54}'], + ['\u{1e56}','\u{1e56}'], + ['\u{1e58}','\u{1e58}'], + ['\u{1e5a}','\u{1e5a}'], + ['\u{1e5c}','\u{1e5c}'], + ['\u{1e5e}','\u{1e5e}'], + ['\u{1e60}','\u{1e60}'], + ['\u{1e62}','\u{1e62}'], + ['\u{1e64}','\u{1e64}'], + ['\u{1e66}','\u{1e66}'], + ['\u{1e68}','\u{1e68}'], + ['\u{1e6a}','\u{1e6a}'], + ['\u{1e6c}','\u{1e6c}'], + ['\u{1e6e}','\u{1e6e}'], + ['\u{1e70}','\u{1e70}'], + ['\u{1e72}','\u{1e72}'], + ['\u{1e74}','\u{1e74}'], + ['\u{1e76}','\u{1e76}'], + ['\u{1e78}','\u{1e78}'], + ['\u{1e7a}','\u{1e7a}'], + ['\u{1e7c}','\u{1e7c}'], + ['\u{1e7e}','\u{1e7e}'], + ['\u{1e80}','\u{1e80}'], + ['\u{1e82}','\u{1e82}'], + ['\u{1e84}','\u{1e84}'], + ['\u{1e86}','\u{1e86}'], + ['\u{1e88}','\u{1e88}'], + ['\u{1e8a}','\u{1e8a}'], + ['\u{1e8c}','\u{1e8c}'], + ['\u{1e8e}','\u{1e8e}'], + ['\u{1e90}','\u{1e90}'], + ['\u{1e92}','\u{1e92}'], + ['\u{1e94}','\u{1e94}'], + ['\u{1e9e}','\u{1e9e}'], + ['\u{1ea0}','\u{1ea0}'], + ['\u{1ea2}','\u{1ea2}'], + ['\u{1ea4}','\u{1ea4}'], + ['\u{1ea6}','\u{1ea6}'], + ['\u{1ea8}','\u{1ea8}'], + ['\u{1eaa}','\u{1eaa}'], + ['\u{1eac}','\u{1eac}'], + ['\u{1eae}','\u{1eae}'], + ['\u{1eb0}','\u{1eb0}'], + ['\u{1eb2}','\u{1eb2}'], + ['\u{1eb4}','\u{1eb4}'], + ['\u{1eb6}','\u{1eb6}'], + ['\u{1eb8}','\u{1eb8}'], + ['\u{1eba}','\u{1eba}'], + ['\u{1ebc}','\u{1ebc}'], + ['\u{1ebe}','\u{1ebe}'], + ['\u{1ec0}','\u{1ec0}'], + ['\u{1ec2}','\u{1ec2}'], + ['\u{1ec4}','\u{1ec4}'], + ['\u{1ec6}','\u{1ec6}'], + ['\u{1ec8}','\u{1ec8}'], + ['\u{1eca}','\u{1eca}'], + ['\u{1ecc}','\u{1ecc}'], + ['\u{1ece}','\u{1ece}'], + ['\u{1ed0}','\u{1ed0}'], + ['\u{1ed2}','\u{1ed2}'], + ['\u{1ed4}','\u{1ed4}'], + ['\u{1ed6}','\u{1ed6}'], + ['\u{1ed8}','\u{1ed8}'], + ['\u{1eda}','\u{1eda}'], + ['\u{1edc}','\u{1edc}'], + ['\u{1ede}','\u{1ede}'], + ['\u{1ee0}','\u{1ee0}'], + ['\u{1ee2}','\u{1ee2}'], + ['\u{1ee4}','\u{1ee4}'], + ['\u{1ee6}','\u{1ee6}'], + ['\u{1ee8}','\u{1ee8}'], + ['\u{1eea}','\u{1eea}'], + ['\u{1eec}','\u{1eec}'], + ['\u{1eee}','\u{1eee}'], + ['\u{1ef0}','\u{1ef0}'], + ['\u{1ef2}','\u{1ef2}'], + ['\u{1ef4}','\u{1ef4}'], + ['\u{1ef6}','\u{1ef6}'], + ['\u{1ef8}','\u{1ef8}'], + ['\u{1efa}','\u{1efa}'], + ['\u{1efc}','\u{1efc}'], + ['\u{1efe}','\u{1efe}'], + ['\u{1f08}','\u{1f0f}'], + ['\u{1f18}','\u{1f1d}'], + ['\u{1f28}','\u{1f2f}'], + ['\u{1f38}','\u{1f3f}'], + ['\u{1f48}','\u{1f4d}'], + ['\u{1f59}','\u{1f59}'], + ['\u{1f5b}','\u{1f5b}'], + ['\u{1f5d}','\u{1f5d}'], + ['\u{1f5f}','\u{1f5f}'], + ['\u{1f68}','\u{1f6f}'], + ['\u{1fb8}','\u{1fbb}'], + ['\u{1fc8}','\u{1fcb}'], + ['\u{1fd8}','\u{1fdb}'], + ['\u{1fe8}','\u{1fec}'], + ['\u{1ff8}','\u{1ffb}'], + ['\u{2102}','\u{2102}'], + ['\u{2107}','\u{2107}'], + ['\u{210b}','\u{210d}'], + ['\u{2110}','\u{2112}'], + ['\u{2115}','\u{2115}'], + ['\u{2119}','\u{211d}'], + ['\u{2124}','\u{2124}'], + ['\u{2126}','\u{2126}'], + ['\u{2128}','\u{2128}'], + ['\u{212a}','\u{212d}'], + ['\u{2130}','\u{2133}'], + ['\u{213e}','\u{213f}'], + ['\u{2145}','\u{2145}'], + ['\u{2183}','\u{2183}'], + ['\u{2c00}','\u{2c2e}'], + ['\u{2c60}','\u{2c60}'], + ['\u{2c62}','\u{2c64}'], + ['\u{2c67}','\u{2c67}'], + ['\u{2c69}','\u{2c69}'], + ['\u{2c6b}','\u{2c6b}'], + ['\u{2c6d}','\u{2c70}'], + ['\u{2c72}','\u{2c72}'], + ['\u{2c75}','\u{2c75}'], + ['\u{2c7e}','\u{2c80}'], + ['\u{2c82}','\u{2c82}'], + ['\u{2c84}','\u{2c84}'], + ['\u{2c86}','\u{2c86}'], + ['\u{2c88}','\u{2c88}'], + ['\u{2c8a}','\u{2c8a}'], + ['\u{2c8c}','\u{2c8c}'], + ['\u{2c8e}','\u{2c8e}'], + ['\u{2c90}','\u{2c90}'], + ['\u{2c92}','\u{2c92}'], + ['\u{2c94}','\u{2c94}'], + ['\u{2c96}','\u{2c96}'], + ['\u{2c98}','\u{2c98}'], + ['\u{2c9a}','\u{2c9a}'], + ['\u{2c9c}','\u{2c9c}'], + ['\u{2c9e}','\u{2c9e}'], + ['\u{2ca0}','\u{2ca0}'], + ['\u{2ca2}','\u{2ca2}'], + ['\u{2ca4}','\u{2ca4}'], + ['\u{2ca6}','\u{2ca6}'], + ['\u{2ca8}','\u{2ca8}'], + ['\u{2caa}','\u{2caa}'], + ['\u{2cac}','\u{2cac}'], + ['\u{2cae}','\u{2cae}'], + ['\u{2cb0}','\u{2cb0}'], + ['\u{2cb2}','\u{2cb2}'], + ['\u{2cb4}','\u{2cb4}'], + ['\u{2cb6}','\u{2cb6}'], + ['\u{2cb8}','\u{2cb8}'], + ['\u{2cba}','\u{2cba}'], + ['\u{2cbc}','\u{2cbc}'], + ['\u{2cbe}','\u{2cbe}'], + ['\u{2cc0}','\u{2cc0}'], + ['\u{2cc2}','\u{2cc2}'], + ['\u{2cc4}','\u{2cc4}'], + ['\u{2cc6}','\u{2cc6}'], + ['\u{2cc8}','\u{2cc8}'], + ['\u{2cca}','\u{2cca}'], + ['\u{2ccc}','\u{2ccc}'], + ['\u{2cce}','\u{2cce}'], + ['\u{2cd0}','\u{2cd0}'], + ['\u{2cd2}','\u{2cd2}'], + ['\u{2cd4}','\u{2cd4}'], + ['\u{2cd6}','\u{2cd6}'], + ['\u{2cd8}','\u{2cd8}'], + ['\u{2cda}','\u{2cda}'], + ['\u{2cdc}','\u{2cdc}'], + ['\u{2cde}','\u{2cde}'], + ['\u{2ce0}','\u{2ce0}'], + ['\u{2ce2}','\u{2ce2}'], + ['\u{2ceb}','\u{2ceb}'], + ['\u{2ced}','\u{2ced}'], + ['\u{2cf2}','\u{2cf2}'], + ['\u{a640}','\u{a640}'], + ['\u{a642}','\u{a642}'], + ['\u{a644}','\u{a644}'], + ['\u{a646}','\u{a646}'], + ['\u{a648}','\u{a648}'], + ['\u{a64a}','\u{a64a}'], + ['\u{a64c}','\u{a64c}'], + ['\u{a64e}','\u{a64e}'], + ['\u{a650}','\u{a650}'], + ['\u{a652}','\u{a652}'], + ['\u{a654}','\u{a654}'], + ['\u{a656}','\u{a656}'], + ['\u{a658}','\u{a658}'], + ['\u{a65a}','\u{a65a}'], + ['\u{a65c}','\u{a65c}'], + ['\u{a65e}','\u{a65e}'], + ['\u{a660}','\u{a660}'], + ['\u{a662}','\u{a662}'], + ['\u{a664}','\u{a664}'], + ['\u{a666}','\u{a666}'], + ['\u{a668}','\u{a668}'], + ['\u{a66a}','\u{a66a}'], + ['\u{a66c}','\u{a66c}'], + ['\u{a680}','\u{a680}'], + ['\u{a682}','\u{a682}'], + ['\u{a684}','\u{a684}'], + ['\u{a686}','\u{a686}'], + ['\u{a688}','\u{a688}'], + ['\u{a68a}','\u{a68a}'], + ['\u{a68c}','\u{a68c}'], + ['\u{a68e}','\u{a68e}'], + ['\u{a690}','\u{a690}'], + ['\u{a692}','\u{a692}'], + ['\u{a694}','\u{a694}'], + ['\u{a696}','\u{a696}'], + ['\u{a722}','\u{a722}'], + ['\u{a724}','\u{a724}'], + ['\u{a726}','\u{a726}'], + ['\u{a728}','\u{a728}'], + ['\u{a72a}','\u{a72a}'], + ['\u{a72c}','\u{a72c}'], + ['\u{a72e}','\u{a72e}'], + ['\u{a732}','\u{a732}'], + ['\u{a734}','\u{a734}'], + ['\u{a736}','\u{a736}'], + ['\u{a738}','\u{a738}'], + ['\u{a73a}','\u{a73a}'], + ['\u{a73c}','\u{a73c}'], + ['\u{a73e}','\u{a73e}'], + ['\u{a740}','\u{a740}'], + ['\u{a742}','\u{a742}'], + ['\u{a744}','\u{a744}'], + ['\u{a746}','\u{a746}'], + ['\u{a748}','\u{a748}'], + ['\u{a74a}','\u{a74a}'], + ['\u{a74c}','\u{a74c}'], + ['\u{a74e}','\u{a74e}'], + ['\u{a750}','\u{a750}'], + ['\u{a752}','\u{a752}'], + ['\u{a754}','\u{a754}'], + ['\u{a756}','\u{a756}'], + ['\u{a758}','\u{a758}'], + ['\u{a75a}','\u{a75a}'], + ['\u{a75c}','\u{a75c}'], + ['\u{a75e}','\u{a75e}'], + ['\u{a760}','\u{a760}'], + ['\u{a762}','\u{a762}'], + ['\u{a764}','\u{a764}'], + ['\u{a766}','\u{a766}'], + ['\u{a768}','\u{a768}'], + ['\u{a76a}','\u{a76a}'], + ['\u{a76c}','\u{a76c}'], + ['\u{a76e}','\u{a76e}'], + ['\u{a779}','\u{a779}'], + ['\u{a77b}','\u{a77b}'], + ['\u{a77d}','\u{a77e}'], + ['\u{a780}','\u{a780}'], + ['\u{a782}','\u{a782}'], + ['\u{a784}','\u{a784}'], + ['\u{a786}','\u{a786}'], + ['\u{a78b}','\u{a78b}'], + ['\u{a78d}','\u{a78d}'], + ['\u{a790}','\u{a790}'], + ['\u{a792}','\u{a792}'], + ['\u{a7a0}','\u{a7a0}'], + ['\u{a7a2}','\u{a7a2}'], + ['\u{a7a4}','\u{a7a4}'], + ['\u{a7a6}','\u{a7a6}'], + ['\u{a7a8}','\u{a7a8}'], + ['\u{a7aa}','\u{a7aa}'], + ['\u{ff21}','\u{ff3a}'], + ['\u{10400}','\u{10427}'], + ['\u{1d400}','\u{1d419}'], + ['\u{1d434}','\u{1d44d}'], + ['\u{1d468}','\u{1d481}'], + ['\u{1d49c}','\u{1d49c}'], + ['\u{1d49e}','\u{1d49f}'], + ['\u{1d4a2}','\u{1d4a2}'], + ['\u{1d4a5}','\u{1d4a6}'], + ['\u{1d4a9}','\u{1d4ac}'], + ['\u{1d4ae}','\u{1d4b5}'], + ['\u{1d4d0}','\u{1d4e9}'], + ['\u{1d504}','\u{1d505}'], + ['\u{1d507}','\u{1d50a}'], + ['\u{1d50d}','\u{1d514}'], + ['\u{1d516}','\u{1d51c}'], + ['\u{1d538}','\u{1d539}'], + ['\u{1d53b}','\u{1d53e}'], + ['\u{1d540}','\u{1d544}'], + ['\u{1d546}','\u{1d546}'], + ['\u{1d54a}','\u{1d550}'], + ['\u{1d56c}','\u{1d585}'], + ['\u{1d5a0}','\u{1d5b9}'], + ['\u{1d5d4}','\u{1d5ed}'], + ['\u{1d608}','\u{1d621}'], + ['\u{1d63c}','\u{1d655}'], + ['\u{1d670}','\u{1d689}'], + ['\u{1d6a8}','\u{1d6c0}'], + ['\u{1d6e2}','\u{1d6fa}'], + ['\u{1d71c}','\u{1d734}'], + ['\u{1d756}','\u{1d76e}'], + ['\u{1d790}','\u{1d7a8}'], + ['\u{1d7ca}','\u{1d7ca}'], +] + +const tablower = [ + ['\u{61}','\u{7a}'], + ['\u{b5}','\u{b5}'], + ['\u{df}','\u{f6}'], + ['\u{f8}','\u{ff}'], + ['\u{101}','\u{101}'], + ['\u{103}','\u{103}'], + ['\u{105}','\u{105}'], + ['\u{107}','\u{107}'], + ['\u{109}','\u{109}'], + ['\u{10b}','\u{10b}'], + ['\u{10d}','\u{10d}'], + ['\u{10f}','\u{10f}'], + ['\u{111}','\u{111}'], + ['\u{113}','\u{113}'], + ['\u{115}','\u{115}'], + ['\u{117}','\u{117}'], + ['\u{119}','\u{119}'], + ['\u{11b}','\u{11b}'], + ['\u{11d}','\u{11d}'], + ['\u{11f}','\u{11f}'], + ['\u{121}','\u{121}'], + ['\u{123}','\u{123}'], + ['\u{125}','\u{125}'], + ['\u{127}','\u{127}'], + ['\u{129}','\u{129}'], + ['\u{12b}','\u{12b}'], + ['\u{12d}','\u{12d}'], + ['\u{12f}','\u{12f}'], + ['\u{131}','\u{131}'], + ['\u{133}','\u{133}'], + ['\u{135}','\u{135}'], + ['\u{137}','\u{138}'], + ['\u{13a}','\u{13a}'], + ['\u{13c}','\u{13c}'], + ['\u{13e}','\u{13e}'], + ['\u{140}','\u{140}'], + ['\u{142}','\u{142}'], + ['\u{144}','\u{144}'], + ['\u{146}','\u{146}'], + ['\u{148}','\u{149}'], + ['\u{14b}','\u{14b}'], + ['\u{14d}','\u{14d}'], + ['\u{14f}','\u{14f}'], + ['\u{151}','\u{151}'], + ['\u{153}','\u{153}'], + ['\u{155}','\u{155}'], + ['\u{157}','\u{157}'], + ['\u{159}','\u{159}'], + ['\u{15b}','\u{15b}'], + ['\u{15d}','\u{15d}'], + ['\u{15f}','\u{15f}'], + ['\u{161}','\u{161}'], + ['\u{163}','\u{163}'], + ['\u{165}','\u{165}'], + ['\u{167}','\u{167}'], + ['\u{169}','\u{169}'], + ['\u{16b}','\u{16b}'], + ['\u{16d}','\u{16d}'], + ['\u{16f}','\u{16f}'], + ['\u{171}','\u{171}'], + ['\u{173}','\u{173}'], + ['\u{175}','\u{175}'], + ['\u{177}','\u{177}'], + ['\u{17a}','\u{17a}'], + ['\u{17c}','\u{17c}'], + ['\u{17e}','\u{180}'], + ['\u{183}','\u{183}'], + ['\u{185}','\u{185}'], + ['\u{188}','\u{188}'], + ['\u{18c}','\u{18d}'], + ['\u{192}','\u{192}'], + ['\u{195}','\u{195}'], + ['\u{199}','\u{19b}'], + ['\u{19e}','\u{19e}'], + ['\u{1a1}','\u{1a1}'], + ['\u{1a3}','\u{1a3}'], + ['\u{1a5}','\u{1a5}'], + ['\u{1a8}','\u{1a8}'], + ['\u{1aa}','\u{1ab}'], + ['\u{1ad}','\u{1ad}'], + ['\u{1b0}','\u{1b0}'], + ['\u{1b4}','\u{1b4}'], + ['\u{1b6}','\u{1b6}'], + ['\u{1b9}','\u{1ba}'], + ['\u{1bd}','\u{1bf}'], + ['\u{1c6}','\u{1c6}'], + ['\u{1c9}','\u{1c9}'], + ['\u{1cc}','\u{1cc}'], + ['\u{1ce}','\u{1ce}'], + ['\u{1d0}','\u{1d0}'], + ['\u{1d2}','\u{1d2}'], + ['\u{1d4}','\u{1d4}'], + ['\u{1d6}','\u{1d6}'], + ['\u{1d8}','\u{1d8}'], + ['\u{1da}','\u{1da}'], + ['\u{1dc}','\u{1dd}'], + ['\u{1df}','\u{1df}'], + ['\u{1e1}','\u{1e1}'], + ['\u{1e3}','\u{1e3}'], + ['\u{1e5}','\u{1e5}'], + ['\u{1e7}','\u{1e7}'], + ['\u{1e9}','\u{1e9}'], + ['\u{1eb}','\u{1eb}'], + ['\u{1ed}','\u{1ed}'], + ['\u{1ef}','\u{1f0}'], + ['\u{1f3}','\u{1f3}'], + ['\u{1f5}','\u{1f5}'], + ['\u{1f9}','\u{1f9}'], + ['\u{1fb}','\u{1fb}'], + ['\u{1fd}','\u{1fd}'], + ['\u{1ff}','\u{1ff}'], + ['\u{201}','\u{201}'], + ['\u{203}','\u{203}'], + ['\u{205}','\u{205}'], + ['\u{207}','\u{207}'], + ['\u{209}','\u{209}'], + ['\u{20b}','\u{20b}'], + ['\u{20d}','\u{20d}'], + ['\u{20f}','\u{20f}'], + ['\u{211}','\u{211}'], + ['\u{213}','\u{213}'], + ['\u{215}','\u{215}'], + ['\u{217}','\u{217}'], + ['\u{219}','\u{219}'], + ['\u{21b}','\u{21b}'], + ['\u{21d}','\u{21d}'], + ['\u{21f}','\u{21f}'], + ['\u{221}','\u{221}'], + ['\u{223}','\u{223}'], + ['\u{225}','\u{225}'], + ['\u{227}','\u{227}'], + ['\u{229}','\u{229}'], + ['\u{22b}','\u{22b}'], + ['\u{22d}','\u{22d}'], + ['\u{22f}','\u{22f}'], + ['\u{231}','\u{231}'], + ['\u{233}','\u{239}'], + ['\u{23c}','\u{23c}'], + ['\u{23f}','\u{240}'], + ['\u{242}','\u{242}'], + ['\u{247}','\u{247}'], + ['\u{249}','\u{249}'], + ['\u{24b}','\u{24b}'], + ['\u{24d}','\u{24d}'], + ['\u{24f}','\u{293}'], + ['\u{295}','\u{2af}'], + ['\u{371}','\u{371}'], + ['\u{373}','\u{373}'], + ['\u{377}','\u{377}'], + ['\u{37b}','\u{37d}'], + ['\u{390}','\u{390}'], + ['\u{3ac}','\u{3ce}'], + ['\u{3d0}','\u{3d1}'], + ['\u{3d5}','\u{3d7}'], + ['\u{3d9}','\u{3d9}'], + ['\u{3db}','\u{3db}'], + ['\u{3dd}','\u{3dd}'], + ['\u{3df}','\u{3df}'], + ['\u{3e1}','\u{3e1}'], + ['\u{3e3}','\u{3e3}'], + ['\u{3e5}','\u{3e5}'], + ['\u{3e7}','\u{3e7}'], + ['\u{3e9}','\u{3e9}'], + ['\u{3eb}','\u{3eb}'], + ['\u{3ed}','\u{3ed}'], + ['\u{3ef}','\u{3f3}'], + ['\u{3f5}','\u{3f5}'], + ['\u{3f8}','\u{3f8}'], + ['\u{3fb}','\u{3fc}'], + ['\u{430}','\u{45f}'], + ['\u{461}','\u{461}'], + ['\u{463}','\u{463}'], + ['\u{465}','\u{465}'], + ['\u{467}','\u{467}'], + ['\u{469}','\u{469}'], + ['\u{46b}','\u{46b}'], + ['\u{46d}','\u{46d}'], + ['\u{46f}','\u{46f}'], + ['\u{471}','\u{471}'], + ['\u{473}','\u{473}'], + ['\u{475}','\u{475}'], + ['\u{477}','\u{477}'], + ['\u{479}','\u{479}'], + ['\u{47b}','\u{47b}'], + ['\u{47d}','\u{47d}'], + ['\u{47f}','\u{47f}'], + ['\u{481}','\u{481}'], + ['\u{48b}','\u{48b}'], + ['\u{48d}','\u{48d}'], + ['\u{48f}','\u{48f}'], + ['\u{491}','\u{491}'], + ['\u{493}','\u{493}'], + ['\u{495}','\u{495}'], + ['\u{497}','\u{497}'], + ['\u{499}','\u{499}'], + ['\u{49b}','\u{49b}'], + ['\u{49d}','\u{49d}'], + ['\u{49f}','\u{49f}'], + ['\u{4a1}','\u{4a1}'], + ['\u{4a3}','\u{4a3}'], + ['\u{4a5}','\u{4a5}'], + ['\u{4a7}','\u{4a7}'], + ['\u{4a9}','\u{4a9}'], + ['\u{4ab}','\u{4ab}'], + ['\u{4ad}','\u{4ad}'], + ['\u{4af}','\u{4af}'], + ['\u{4b1}','\u{4b1}'], + ['\u{4b3}','\u{4b3}'], + ['\u{4b5}','\u{4b5}'], + ['\u{4b7}','\u{4b7}'], + ['\u{4b9}','\u{4b9}'], + ['\u{4bb}','\u{4bb}'], + ['\u{4bd}','\u{4bd}'], + ['\u{4bf}','\u{4bf}'], + ['\u{4c2}','\u{4c2}'], + ['\u{4c4}','\u{4c4}'], + ['\u{4c6}','\u{4c6}'], + ['\u{4c8}','\u{4c8}'], + ['\u{4ca}','\u{4ca}'], + ['\u{4cc}','\u{4cc}'], + ['\u{4ce}','\u{4cf}'], + ['\u{4d1}','\u{4d1}'], + ['\u{4d3}','\u{4d3}'], + ['\u{4d5}','\u{4d5}'], + ['\u{4d7}','\u{4d7}'], + ['\u{4d9}','\u{4d9}'], + ['\u{4db}','\u{4db}'], + ['\u{4dd}','\u{4dd}'], + ['\u{4df}','\u{4df}'], + ['\u{4e1}','\u{4e1}'], + ['\u{4e3}','\u{4e3}'], + ['\u{4e5}','\u{4e5}'], + ['\u{4e7}','\u{4e7}'], + ['\u{4e9}','\u{4e9}'], + ['\u{4eb}','\u{4eb}'], + ['\u{4ed}','\u{4ed}'], + ['\u{4ef}','\u{4ef}'], + ['\u{4f1}','\u{4f1}'], + ['\u{4f3}','\u{4f3}'], + ['\u{4f5}','\u{4f5}'], + ['\u{4f7}','\u{4f7}'], + ['\u{4f9}','\u{4f9}'], + ['\u{4fb}','\u{4fb}'], + ['\u{4fd}','\u{4fd}'], + ['\u{4ff}','\u{4ff}'], + ['\u{501}','\u{501}'], + ['\u{503}','\u{503}'], + ['\u{505}','\u{505}'], + ['\u{507}','\u{507}'], + ['\u{509}','\u{509}'], + ['\u{50b}','\u{50b}'], + ['\u{50d}','\u{50d}'], + ['\u{50f}','\u{50f}'], + ['\u{511}','\u{511}'], + ['\u{513}','\u{513}'], + ['\u{515}','\u{515}'], + ['\u{517}','\u{517}'], + ['\u{519}','\u{519}'], + ['\u{51b}','\u{51b}'], + ['\u{51d}','\u{51d}'], + ['\u{51f}','\u{51f}'], + ['\u{521}','\u{521}'], + ['\u{523}','\u{523}'], + ['\u{525}','\u{525}'], + ['\u{527}','\u{527}'], + ['\u{561}','\u{587}'], + ['\u{1d00}','\u{1d2b}'], + ['\u{1d6b}','\u{1d77}'], + ['\u{1d79}','\u{1d9a}'], + ['\u{1e01}','\u{1e01}'], + ['\u{1e03}','\u{1e03}'], + ['\u{1e05}','\u{1e05}'], + ['\u{1e07}','\u{1e07}'], + ['\u{1e09}','\u{1e09}'], + ['\u{1e0b}','\u{1e0b}'], + ['\u{1e0d}','\u{1e0d}'], + ['\u{1e0f}','\u{1e0f}'], + ['\u{1e11}','\u{1e11}'], + ['\u{1e13}','\u{1e13}'], + ['\u{1e15}','\u{1e15}'], + ['\u{1e17}','\u{1e17}'], + ['\u{1e19}','\u{1e19}'], + ['\u{1e1b}','\u{1e1b}'], + ['\u{1e1d}','\u{1e1d}'], + ['\u{1e1f}','\u{1e1f}'], + ['\u{1e21}','\u{1e21}'], + ['\u{1e23}','\u{1e23}'], + ['\u{1e25}','\u{1e25}'], + ['\u{1e27}','\u{1e27}'], + ['\u{1e29}','\u{1e29}'], + ['\u{1e2b}','\u{1e2b}'], + ['\u{1e2d}','\u{1e2d}'], + ['\u{1e2f}','\u{1e2f}'], + ['\u{1e31}','\u{1e31}'], + ['\u{1e33}','\u{1e33}'], + ['\u{1e35}','\u{1e35}'], + ['\u{1e37}','\u{1e37}'], + ['\u{1e39}','\u{1e39}'], + ['\u{1e3b}','\u{1e3b}'], + ['\u{1e3d}','\u{1e3d}'], + ['\u{1e3f}','\u{1e3f}'], + ['\u{1e41}','\u{1e41}'], + ['\u{1e43}','\u{1e43}'], + ['\u{1e45}','\u{1e45}'], + ['\u{1e47}','\u{1e47}'], + ['\u{1e49}','\u{1e49}'], + ['\u{1e4b}','\u{1e4b}'], + ['\u{1e4d}','\u{1e4d}'], + ['\u{1e4f}','\u{1e4f}'], + ['\u{1e51}','\u{1e51}'], + ['\u{1e53}','\u{1e53}'], + ['\u{1e55}','\u{1e55}'], + ['\u{1e57}','\u{1e57}'], + ['\u{1e59}','\u{1e59}'], + ['\u{1e5b}','\u{1e5b}'], + ['\u{1e5d}','\u{1e5d}'], + ['\u{1e5f}','\u{1e5f}'], + ['\u{1e61}','\u{1e61}'], + ['\u{1e63}','\u{1e63}'], + ['\u{1e65}','\u{1e65}'], + ['\u{1e67}','\u{1e67}'], + ['\u{1e69}','\u{1e69}'], + ['\u{1e6b}','\u{1e6b}'], + ['\u{1e6d}','\u{1e6d}'], + ['\u{1e6f}','\u{1e6f}'], + ['\u{1e71}','\u{1e71}'], + ['\u{1e73}','\u{1e73}'], + ['\u{1e75}','\u{1e75}'], + ['\u{1e77}','\u{1e77}'], + ['\u{1e79}','\u{1e79}'], + ['\u{1e7b}','\u{1e7b}'], + ['\u{1e7d}','\u{1e7d}'], + ['\u{1e7f}','\u{1e7f}'], + ['\u{1e81}','\u{1e81}'], + ['\u{1e83}','\u{1e83}'], + ['\u{1e85}','\u{1e85}'], + ['\u{1e87}','\u{1e87}'], + ['\u{1e89}','\u{1e89}'], + ['\u{1e8b}','\u{1e8b}'], + ['\u{1e8d}','\u{1e8d}'], + ['\u{1e8f}','\u{1e8f}'], + ['\u{1e91}','\u{1e91}'], + ['\u{1e93}','\u{1e93}'], + ['\u{1e95}','\u{1e9d}'], + ['\u{1e9f}','\u{1e9f}'], + ['\u{1ea1}','\u{1ea1}'], + ['\u{1ea3}','\u{1ea3}'], + ['\u{1ea5}','\u{1ea5}'], + ['\u{1ea7}','\u{1ea7}'], + ['\u{1ea9}','\u{1ea9}'], + ['\u{1eab}','\u{1eab}'], + ['\u{1ead}','\u{1ead}'], + ['\u{1eaf}','\u{1eaf}'], + ['\u{1eb1}','\u{1eb1}'], + ['\u{1eb3}','\u{1eb3}'], + ['\u{1eb5}','\u{1eb5}'], + ['\u{1eb7}','\u{1eb7}'], + ['\u{1eb9}','\u{1eb9}'], + ['\u{1ebb}','\u{1ebb}'], + ['\u{1ebd}','\u{1ebd}'], + ['\u{1ebf}','\u{1ebf}'], + ['\u{1ec1}','\u{1ec1}'], + ['\u{1ec3}','\u{1ec3}'], + ['\u{1ec5}','\u{1ec5}'], + ['\u{1ec7}','\u{1ec7}'], + ['\u{1ec9}','\u{1ec9}'], + ['\u{1ecb}','\u{1ecb}'], + ['\u{1ecd}','\u{1ecd}'], + ['\u{1ecf}','\u{1ecf}'], + ['\u{1ed1}','\u{1ed1}'], + ['\u{1ed3}','\u{1ed3}'], + ['\u{1ed5}','\u{1ed5}'], + ['\u{1ed7}','\u{1ed7}'], + ['\u{1ed9}','\u{1ed9}'], + ['\u{1edb}','\u{1edb}'], + ['\u{1edd}','\u{1edd}'], + ['\u{1edf}','\u{1edf}'], + ['\u{1ee1}','\u{1ee1}'], + ['\u{1ee3}','\u{1ee3}'], + ['\u{1ee5}','\u{1ee5}'], + ['\u{1ee7}','\u{1ee7}'], + ['\u{1ee9}','\u{1ee9}'], + ['\u{1eeb}','\u{1eeb}'], + ['\u{1eed}','\u{1eed}'], + ['\u{1eef}','\u{1eef}'], + ['\u{1ef1}','\u{1ef1}'], + ['\u{1ef3}','\u{1ef3}'], + ['\u{1ef5}','\u{1ef5}'], + ['\u{1ef7}','\u{1ef7}'], + ['\u{1ef9}','\u{1ef9}'], + ['\u{1efb}','\u{1efb}'], + ['\u{1efd}','\u{1efd}'], + ['\u{1eff}','\u{1f07}'], + ['\u{1f10}','\u{1f15}'], + ['\u{1f20}','\u{1f27}'], + ['\u{1f30}','\u{1f37}'], + ['\u{1f40}','\u{1f45}'], + ['\u{1f50}','\u{1f57}'], + ['\u{1f60}','\u{1f67}'], + ['\u{1f70}','\u{1f7d}'], + ['\u{1f80}','\u{1f87}'], + ['\u{1f90}','\u{1f97}'], + ['\u{1fa0}','\u{1fa7}'], + ['\u{1fb0}','\u{1fb4}'], + ['\u{1fb6}','\u{1fb7}'], + ['\u{1fbe}','\u{1fbe}'], + ['\u{1fc2}','\u{1fc4}'], + ['\u{1fc6}','\u{1fc7}'], + ['\u{1fd0}','\u{1fd3}'], + ['\u{1fd6}','\u{1fd7}'], + ['\u{1fe0}','\u{1fe7}'], + ['\u{1ff2}','\u{1ff4}'], + ['\u{1ff6}','\u{1ff7}'], + ['\u{210a}','\u{210a}'], + ['\u{210e}','\u{210f}'], + ['\u{2113}','\u{2113}'], + ['\u{212f}','\u{212f}'], + ['\u{2134}','\u{2134}'], + ['\u{2139}','\u{2139}'], + ['\u{213c}','\u{213d}'], + ['\u{2146}','\u{2149}'], + ['\u{214e}','\u{214e}'], + ['\u{2184}','\u{2184}'], + ['\u{2c30}','\u{2c5e}'], + ['\u{2c61}','\u{2c61}'], + ['\u{2c65}','\u{2c66}'], + ['\u{2c68}','\u{2c68}'], + ['\u{2c6a}','\u{2c6a}'], + ['\u{2c6c}','\u{2c6c}'], + ['\u{2c71}','\u{2c71}'], + ['\u{2c73}','\u{2c74}'], + ['\u{2c76}','\u{2c7b}'], + ['\u{2c81}','\u{2c81}'], + ['\u{2c83}','\u{2c83}'], + ['\u{2c85}','\u{2c85}'], + ['\u{2c87}','\u{2c87}'], + ['\u{2c89}','\u{2c89}'], + ['\u{2c8b}','\u{2c8b}'], + ['\u{2c8d}','\u{2c8d}'], + ['\u{2c8f}','\u{2c8f}'], + ['\u{2c91}','\u{2c91}'], + ['\u{2c93}','\u{2c93}'], + ['\u{2c95}','\u{2c95}'], + ['\u{2c97}','\u{2c97}'], + ['\u{2c99}','\u{2c99}'], + ['\u{2c9b}','\u{2c9b}'], + ['\u{2c9d}','\u{2c9d}'], + ['\u{2c9f}','\u{2c9f}'], + ['\u{2ca1}','\u{2ca1}'], + ['\u{2ca3}','\u{2ca3}'], + ['\u{2ca5}','\u{2ca5}'], + ['\u{2ca7}','\u{2ca7}'], + ['\u{2ca9}','\u{2ca9}'], + ['\u{2cab}','\u{2cab}'], + ['\u{2cad}','\u{2cad}'], + ['\u{2caf}','\u{2caf}'], + ['\u{2cb1}','\u{2cb1}'], + ['\u{2cb3}','\u{2cb3}'], + ['\u{2cb5}','\u{2cb5}'], + ['\u{2cb7}','\u{2cb7}'], + ['\u{2cb9}','\u{2cb9}'], + ['\u{2cbb}','\u{2cbb}'], + ['\u{2cbd}','\u{2cbd}'], + ['\u{2cbf}','\u{2cbf}'], + ['\u{2cc1}','\u{2cc1}'], + ['\u{2cc3}','\u{2cc3}'], + ['\u{2cc5}','\u{2cc5}'], + ['\u{2cc7}','\u{2cc7}'], + ['\u{2cc9}','\u{2cc9}'], + ['\u{2ccb}','\u{2ccb}'], + ['\u{2ccd}','\u{2ccd}'], + ['\u{2ccf}','\u{2ccf}'], + ['\u{2cd1}','\u{2cd1}'], + ['\u{2cd3}','\u{2cd3}'], + ['\u{2cd5}','\u{2cd5}'], + ['\u{2cd7}','\u{2cd7}'], + ['\u{2cd9}','\u{2cd9}'], + ['\u{2cdb}','\u{2cdb}'], + ['\u{2cdd}','\u{2cdd}'], + ['\u{2cdf}','\u{2cdf}'], + ['\u{2ce1}','\u{2ce1}'], + ['\u{2ce3}','\u{2ce4}'], + ['\u{2cec}','\u{2cec}'], + ['\u{2cee}','\u{2cee}'], + ['\u{2cf3}','\u{2cf3}'], + ['\u{2d00}','\u{2d25}'], + ['\u{2d27}','\u{2d27}'], + ['\u{2d2d}','\u{2d2d}'], + ['\u{a641}','\u{a641}'], + ['\u{a643}','\u{a643}'], + ['\u{a645}','\u{a645}'], + ['\u{a647}','\u{a647}'], + ['\u{a649}','\u{a649}'], + ['\u{a64b}','\u{a64b}'], + ['\u{a64d}','\u{a64d}'], + ['\u{a64f}','\u{a64f}'], + ['\u{a651}','\u{a651}'], + ['\u{a653}','\u{a653}'], + ['\u{a655}','\u{a655}'], + ['\u{a657}','\u{a657}'], + ['\u{a659}','\u{a659}'], + ['\u{a65b}','\u{a65b}'], + ['\u{a65d}','\u{a65d}'], + ['\u{a65f}','\u{a65f}'], + ['\u{a661}','\u{a661}'], + ['\u{a663}','\u{a663}'], + ['\u{a665}','\u{a665}'], + ['\u{a667}','\u{a667}'], + ['\u{a669}','\u{a669}'], + ['\u{a66b}','\u{a66b}'], + ['\u{a66d}','\u{a66d}'], + ['\u{a681}','\u{a681}'], + ['\u{a683}','\u{a683}'], + ['\u{a685}','\u{a685}'], + ['\u{a687}','\u{a687}'], + ['\u{a689}','\u{a689}'], + ['\u{a68b}','\u{a68b}'], + ['\u{a68d}','\u{a68d}'], + ['\u{a68f}','\u{a68f}'], + ['\u{a691}','\u{a691}'], + ['\u{a693}','\u{a693}'], + ['\u{a695}','\u{a695}'], + ['\u{a697}','\u{a697}'], + ['\u{a723}','\u{a723}'], + ['\u{a725}','\u{a725}'], + ['\u{a727}','\u{a727}'], + ['\u{a729}','\u{a729}'], + ['\u{a72b}','\u{a72b}'], + ['\u{a72d}','\u{a72d}'], + ['\u{a72f}','\u{a731}'], + ['\u{a733}','\u{a733}'], + ['\u{a735}','\u{a735}'], + ['\u{a737}','\u{a737}'], + ['\u{a739}','\u{a739}'], + ['\u{a73b}','\u{a73b}'], + ['\u{a73d}','\u{a73d}'], + ['\u{a73f}','\u{a73f}'], + ['\u{a741}','\u{a741}'], + ['\u{a743}','\u{a743}'], + ['\u{a745}','\u{a745}'], + ['\u{a747}','\u{a747}'], + ['\u{a749}','\u{a749}'], + ['\u{a74b}','\u{a74b}'], + ['\u{a74d}','\u{a74d}'], + ['\u{a74f}','\u{a74f}'], + ['\u{a751}','\u{a751}'], + ['\u{a753}','\u{a753}'], + ['\u{a755}','\u{a755}'], + ['\u{a757}','\u{a757}'], + ['\u{a759}','\u{a759}'], + ['\u{a75b}','\u{a75b}'], + ['\u{a75d}','\u{a75d}'], + ['\u{a75f}','\u{a75f}'], + ['\u{a761}','\u{a761}'], + ['\u{a763}','\u{a763}'], + ['\u{a765}','\u{a765}'], + ['\u{a767}','\u{a767}'], + ['\u{a769}','\u{a769}'], + ['\u{a76b}','\u{a76b}'], + ['\u{a76d}','\u{a76d}'], + ['\u{a76f}','\u{a76f}'], + ['\u{a771}','\u{a778}'], + ['\u{a77a}','\u{a77a}'], + ['\u{a77c}','\u{a77c}'], + ['\u{a77f}','\u{a77f}'], + ['\u{a781}','\u{a781}'], + ['\u{a783}','\u{a783}'], + ['\u{a785}','\u{a785}'], + ['\u{a787}','\u{a787}'], + ['\u{a78c}','\u{a78c}'], + ['\u{a78e}','\u{a78e}'], + ['\u{a791}','\u{a791}'], + ['\u{a793}','\u{a793}'], + ['\u{a7a1}','\u{a7a1}'], + ['\u{a7a3}','\u{a7a3}'], + ['\u{a7a5}','\u{a7a5}'], + ['\u{a7a7}','\u{a7a7}'], + ['\u{a7a9}','\u{a7a9}'], + ['\u{a7fa}','\u{a7fa}'], + ['\u{fb00}','\u{fb06}'], + ['\u{fb13}','\u{fb17}'], + ['\u{ff41}','\u{ff5a}'], + ['\u{10428}','\u{1044f}'], + ['\u{1d41a}','\u{1d433}'], + ['\u{1d44e}','\u{1d454}'], + ['\u{1d456}','\u{1d467}'], + ['\u{1d482}','\u{1d49b}'], + ['\u{1d4b6}','\u{1d4b9}'], + ['\u{1d4bb}','\u{1d4bb}'], + ['\u{1d4bd}','\u{1d4c3}'], + ['\u{1d4c5}','\u{1d4cf}'], + ['\u{1d4ea}','\u{1d503}'], + ['\u{1d51e}','\u{1d537}'], + ['\u{1d552}','\u{1d56b}'], + ['\u{1d586}','\u{1d59f}'], + ['\u{1d5ba}','\u{1d5d3}'], + ['\u{1d5ee}','\u{1d607}'], + ['\u{1d622}','\u{1d63b}'], + ['\u{1d656}','\u{1d66f}'], + ['\u{1d68a}','\u{1d6a5}'], + ['\u{1d6c2}','\u{1d6da}'], + ['\u{1d6dc}','\u{1d6e1}'], + ['\u{1d6fc}','\u{1d714}'], + ['\u{1d716}','\u{1d71b}'], + ['\u{1d736}','\u{1d74e}'], + ['\u{1d750}','\u{1d755}'], + ['\u{1d770}','\u{1d788}'], + ['\u{1d78a}','\u{1d78f}'], + ['\u{1d7aa}','\u{1d7c2}'], + ['\u{1d7c4}','\u{1d7c9}'], + ['\u{1d7cb}','\u{1d7cb}'], +] + +const tabtitle = [ + ['\u{1c5}','\u{1c5}'], + ['\u{1c8}','\u{1c8}'], + ['\u{1cb}','\u{1cb}'], + ['\u{1f2}','\u{1f2}'], + ['\u{1f88}','\u{1f8f}'], + ['\u{1f98}','\u{1f9f}'], + ['\u{1fa8}','\u{1faf}'], + ['\u{1fbc}','\u{1fbc}'], + ['\u{1fcc}','\u{1fcc}'], + ['\u{1ffc}','\u{1ffc}'], +] + +const tabword = [ + ['\u{30}','\u{39}'], + ['\u{41}','\u{5a}'], + ['\u{5f}','\u{5f}'], + ['\u{61}','\u{7a}'], + ['\u{aa}','\u{aa}'], + ['\u{b5}','\u{b5}'], + ['\u{ba}','\u{ba}'], + ['\u{c0}','\u{d6}'], + ['\u{d8}','\u{f6}'], + ['\u{f8}','\u{2c1}'], + ['\u{2c6}','\u{2d1}'], + ['\u{2e0}','\u{2e4}'], + ['\u{2ec}','\u{2ec}'], + ['\u{2ee}','\u{2ee}'], + ['\u{370}','\u{374}'], + ['\u{376}','\u{377}'], + ['\u{37a}','\u{37d}'], + ['\u{386}','\u{386}'], + ['\u{388}','\u{38a}'], + ['\u{38c}','\u{38c}'], + ['\u{38e}','\u{3a1}'], + ['\u{3a3}','\u{3f5}'], + ['\u{3f7}','\u{481}'], + ['\u{48a}','\u{527}'], + ['\u{531}','\u{556}'], + ['\u{559}','\u{559}'], + ['\u{561}','\u{587}'], + ['\u{5d0}','\u{5ea}'], + ['\u{5f0}','\u{5f2}'], + ['\u{620}','\u{64a}'], + ['\u{660}','\u{669}'], + ['\u{66e}','\u{66f}'], + ['\u{671}','\u{6d3}'], + ['\u{6d5}','\u{6d5}'], + ['\u{6e5}','\u{6e6}'], + ['\u{6ee}','\u{6fc}'], + ['\u{6ff}','\u{6ff}'], + ['\u{710}','\u{710}'], + ['\u{712}','\u{72f}'], + ['\u{74d}','\u{7a5}'], + ['\u{7b1}','\u{7b1}'], + ['\u{7c0}','\u{7ea}'], + ['\u{7f4}','\u{7f5}'], + ['\u{7fa}','\u{7fa}'], + ['\u{800}','\u{815}'], + ['\u{81a}','\u{81a}'], + ['\u{824}','\u{824}'], + ['\u{828}','\u{828}'], + ['\u{840}','\u{858}'], + ['\u{8a0}','\u{8a0}'], + ['\u{8a2}','\u{8ac}'], + ['\u{904}','\u{939}'], + ['\u{93d}','\u{93d}'], + ['\u{950}','\u{950}'], + ['\u{958}','\u{961}'], + ['\u{966}','\u{96f}'], + ['\u{971}','\u{977}'], + ['\u{979}','\u{97f}'], + ['\u{985}','\u{98c}'], + ['\u{98f}','\u{990}'], + ['\u{993}','\u{9a8}'], + ['\u{9aa}','\u{9b0}'], + ['\u{9b2}','\u{9b2}'], + ['\u{9b6}','\u{9b9}'], + ['\u{9bd}','\u{9bd}'], + ['\u{9ce}','\u{9ce}'], + ['\u{9dc}','\u{9dd}'], + ['\u{9df}','\u{9e1}'], + ['\u{9e6}','\u{9f1}'], + ['\u{a05}','\u{a0a}'], + ['\u{a0f}','\u{a10}'], + ['\u{a13}','\u{a28}'], + ['\u{a2a}','\u{a30}'], + ['\u{a32}','\u{a33}'], + ['\u{a35}','\u{a36}'], + ['\u{a38}','\u{a39}'], + ['\u{a59}','\u{a5c}'], + ['\u{a5e}','\u{a5e}'], + ['\u{a66}','\u{a6f}'], + ['\u{a72}','\u{a74}'], + ['\u{a85}','\u{a8d}'], + ['\u{a8f}','\u{a91}'], + ['\u{a93}','\u{aa8}'], + ['\u{aaa}','\u{ab0}'], + ['\u{ab2}','\u{ab3}'], + ['\u{ab5}','\u{ab9}'], + ['\u{abd}','\u{abd}'], + ['\u{ad0}','\u{ad0}'], + ['\u{ae0}','\u{ae1}'], + ['\u{ae6}','\u{aef}'], + ['\u{b05}','\u{b0c}'], + ['\u{b0f}','\u{b10}'], + ['\u{b13}','\u{b28}'], + ['\u{b2a}','\u{b30}'], + ['\u{b32}','\u{b33}'], + ['\u{b35}','\u{b39}'], + ['\u{b3d}','\u{b3d}'], + ['\u{b5c}','\u{b5d}'], + ['\u{b5f}','\u{b61}'], + ['\u{b66}','\u{b6f}'], + ['\u{b71}','\u{b71}'], + ['\u{b83}','\u{b83}'], + ['\u{b85}','\u{b8a}'], + ['\u{b8e}','\u{b90}'], + ['\u{b92}','\u{b95}'], + ['\u{b99}','\u{b9a}'], + ['\u{b9c}','\u{b9c}'], + ['\u{b9e}','\u{b9f}'], + ['\u{ba3}','\u{ba4}'], + ['\u{ba8}','\u{baa}'], + ['\u{bae}','\u{bb9}'], + ['\u{bd0}','\u{bd0}'], + ['\u{be6}','\u{bef}'], + ['\u{c05}','\u{c0c}'], + ['\u{c0e}','\u{c10}'], + ['\u{c12}','\u{c28}'], + ['\u{c2a}','\u{c33}'], + ['\u{c35}','\u{c39}'], + ['\u{c3d}','\u{c3d}'], + ['\u{c58}','\u{c59}'], + ['\u{c60}','\u{c61}'], + ['\u{c66}','\u{c6f}'], + ['\u{c85}','\u{c8c}'], + ['\u{c8e}','\u{c90}'], + ['\u{c92}','\u{ca8}'], + ['\u{caa}','\u{cb3}'], + ['\u{cb5}','\u{cb9}'], + ['\u{cbd}','\u{cbd}'], + ['\u{cde}','\u{cde}'], + ['\u{ce0}','\u{ce1}'], + ['\u{ce6}','\u{cef}'], + ['\u{cf1}','\u{cf2}'], + ['\u{d05}','\u{d0c}'], + ['\u{d0e}','\u{d10}'], + ['\u{d12}','\u{d3a}'], + ['\u{d3d}','\u{d3d}'], + ['\u{d4e}','\u{d4e}'], + ['\u{d60}','\u{d61}'], + ['\u{d66}','\u{d6f}'], + ['\u{d7a}','\u{d7f}'], + ['\u{d85}','\u{d96}'], + ['\u{d9a}','\u{db1}'], + ['\u{db3}','\u{dbb}'], + ['\u{dbd}','\u{dbd}'], + ['\u{dc0}','\u{dc6}'], + ['\u{e01}','\u{e30}'], + ['\u{e32}','\u{e33}'], + ['\u{e40}','\u{e46}'], + ['\u{e50}','\u{e59}'], + ['\u{e81}','\u{e82}'], + ['\u{e84}','\u{e84}'], + ['\u{e87}','\u{e88}'], + ['\u{e8a}','\u{e8a}'], + ['\u{e8d}','\u{e8d}'], + ['\u{e94}','\u{e97}'], + ['\u{e99}','\u{e9f}'], + ['\u{ea1}','\u{ea3}'], + ['\u{ea5}','\u{ea5}'], + ['\u{ea7}','\u{ea7}'], + ['\u{eaa}','\u{eab}'], + ['\u{ead}','\u{eb0}'], + ['\u{eb2}','\u{eb3}'], + ['\u{ebd}','\u{ebd}'], + ['\u{ec0}','\u{ec4}'], + ['\u{ec6}','\u{ec6}'], + ['\u{ed0}','\u{ed9}'], + ['\u{edc}','\u{edf}'], + ['\u{f00}','\u{f00}'], + ['\u{f20}','\u{f29}'], + ['\u{f40}','\u{f47}'], + ['\u{f49}','\u{f6c}'], + ['\u{f88}','\u{f8c}'], + ['\u{1000}','\u{102a}'], + ['\u{103f}','\u{1049}'], + ['\u{1050}','\u{1055}'], + ['\u{105a}','\u{105d}'], + ['\u{1061}','\u{1061}'], + ['\u{1065}','\u{1066}'], + ['\u{106e}','\u{1070}'], + ['\u{1075}','\u{1081}'], + ['\u{108e}','\u{108e}'], + ['\u{1090}','\u{1099}'], + ['\u{10a0}','\u{10c5}'], + ['\u{10c7}','\u{10c7}'], + ['\u{10cd}','\u{10cd}'], + ['\u{10d0}','\u{10fa}'], + ['\u{10fc}','\u{1248}'], + ['\u{124a}','\u{124d}'], + ['\u{1250}','\u{1256}'], + ['\u{1258}','\u{1258}'], + ['\u{125a}','\u{125d}'], + ['\u{1260}','\u{1288}'], + ['\u{128a}','\u{128d}'], + ['\u{1290}','\u{12b0}'], + ['\u{12b2}','\u{12b5}'], + ['\u{12b8}','\u{12be}'], + ['\u{12c0}','\u{12c0}'], + ['\u{12c2}','\u{12c5}'], + ['\u{12c8}','\u{12d6}'], + ['\u{12d8}','\u{1310}'], + ['\u{1312}','\u{1315}'], + ['\u{1318}','\u{135a}'], + ['\u{1380}','\u{138f}'], + ['\u{13a0}','\u{13f4}'], + ['\u{1401}','\u{166c}'], + ['\u{166f}','\u{167f}'], + ['\u{1681}','\u{169a}'], + ['\u{16a0}','\u{16ea}'], + ['\u{1700}','\u{170c}'], + ['\u{170e}','\u{1711}'], + ['\u{1720}','\u{1731}'], + ['\u{1740}','\u{1751}'], + ['\u{1760}','\u{176c}'], + ['\u{176e}','\u{1770}'], + ['\u{1780}','\u{17b3}'], + ['\u{17d7}','\u{17d7}'], + ['\u{17dc}','\u{17dc}'], + ['\u{17e0}','\u{17e9}'], + ['\u{1810}','\u{1819}'], + ['\u{1820}','\u{1877}'], + ['\u{1880}','\u{18a8}'], + ['\u{18aa}','\u{18aa}'], + ['\u{18b0}','\u{18f5}'], + ['\u{1900}','\u{191c}'], + ['\u{1946}','\u{196d}'], + ['\u{1970}','\u{1974}'], + ['\u{1980}','\u{19ab}'], + ['\u{19c1}','\u{19c7}'], + ['\u{19d0}','\u{19d9}'], + ['\u{1a00}','\u{1a16}'], + ['\u{1a20}','\u{1a54}'], + ['\u{1a80}','\u{1a89}'], + ['\u{1a90}','\u{1a99}'], + ['\u{1aa7}','\u{1aa7}'], + ['\u{1b05}','\u{1b33}'], + ['\u{1b45}','\u{1b4b}'], + ['\u{1b50}','\u{1b59}'], + ['\u{1b83}','\u{1ba0}'], + ['\u{1bae}','\u{1be5}'], + ['\u{1c00}','\u{1c23}'], + ['\u{1c40}','\u{1c49}'], + ['\u{1c4d}','\u{1c7d}'], + ['\u{1ce9}','\u{1cec}'], + ['\u{1cee}','\u{1cf1}'], + ['\u{1cf5}','\u{1cf6}'], + ['\u{1d00}','\u{1dbf}'], + ['\u{1e00}','\u{1f15}'], + ['\u{1f18}','\u{1f1d}'], + ['\u{1f20}','\u{1f45}'], + ['\u{1f48}','\u{1f4d}'], + ['\u{1f50}','\u{1f57}'], + ['\u{1f59}','\u{1f59}'], + ['\u{1f5b}','\u{1f5b}'], + ['\u{1f5d}','\u{1f5d}'], + ['\u{1f5f}','\u{1f7d}'], + ['\u{1f80}','\u{1fb4}'], + ['\u{1fb6}','\u{1fbc}'], + ['\u{1fbe}','\u{1fbe}'], + ['\u{1fc2}','\u{1fc4}'], + ['\u{1fc6}','\u{1fcc}'], + ['\u{1fd0}','\u{1fd3}'], + ['\u{1fd6}','\u{1fdb}'], + ['\u{1fe0}','\u{1fec}'], + ['\u{1ff2}','\u{1ff4}'], + ['\u{1ff6}','\u{1ffc}'], + ['\u{2071}','\u{2071}'], + ['\u{207f}','\u{207f}'], + ['\u{2090}','\u{209c}'], + ['\u{2102}','\u{2102}'], + ['\u{2107}','\u{2107}'], + ['\u{210a}','\u{2113}'], + ['\u{2115}','\u{2115}'], + ['\u{2119}','\u{211d}'], + ['\u{2124}','\u{2124}'], + ['\u{2126}','\u{2126}'], + ['\u{2128}','\u{2128}'], + ['\u{212a}','\u{212d}'], + ['\u{212f}','\u{2139}'], + ['\u{213c}','\u{213f}'], + ['\u{2145}','\u{2149}'], + ['\u{214e}','\u{214e}'], + ['\u{2183}','\u{2184}'], + ['\u{2c00}','\u{2c2e}'], + ['\u{2c30}','\u{2c5e}'], + ['\u{2c60}','\u{2ce4}'], + ['\u{2ceb}','\u{2cee}'], + ['\u{2cf2}','\u{2cf3}'], + ['\u{2d00}','\u{2d25}'], + ['\u{2d27}','\u{2d27}'], + ['\u{2d2d}','\u{2d2d}'], + ['\u{2d30}','\u{2d67}'], + ['\u{2d6f}','\u{2d6f}'], + ['\u{2d80}','\u{2d96}'], + ['\u{2da0}','\u{2da6}'], + ['\u{2da8}','\u{2dae}'], + ['\u{2db0}','\u{2db6}'], + ['\u{2db8}','\u{2dbe}'], + ['\u{2dc0}','\u{2dc6}'], + ['\u{2dc8}','\u{2dce}'], + ['\u{2dd0}','\u{2dd6}'], + ['\u{2dd8}','\u{2dde}'], + ['\u{2e2f}','\u{2e2f}'], + ['\u{3005}','\u{3006}'], + ['\u{3031}','\u{3035}'], + ['\u{303b}','\u{303c}'], + ['\u{3041}','\u{3096}'], + ['\u{309d}','\u{309f}'], + ['\u{30a1}','\u{30fa}'], + ['\u{30fc}','\u{30ff}'], + ['\u{3105}','\u{312d}'], + ['\u{3131}','\u{318e}'], + ['\u{31a0}','\u{31ba}'], + ['\u{31f0}','\u{31ff}'], + ['\u{3400}','\u{4db5}'], + ['\u{4e00}','\u{9fcc}'], + ['\u{a000}','\u{a48c}'], + ['\u{a4d0}','\u{a4fd}'], + ['\u{a500}','\u{a60c}'], + ['\u{a610}','\u{a62b}'], + ['\u{a640}','\u{a66e}'], + ['\u{a67f}','\u{a697}'], + ['\u{a6a0}','\u{a6e5}'], + ['\u{a717}','\u{a71f}'], + ['\u{a722}','\u{a788}'], + ['\u{a78b}','\u{a78e}'], + ['\u{a790}','\u{a793}'], + ['\u{a7a0}','\u{a7aa}'], + ['\u{a7f8}','\u{a801}'], + ['\u{a803}','\u{a805}'], + ['\u{a807}','\u{a80a}'], + ['\u{a80c}','\u{a822}'], + ['\u{a840}','\u{a873}'], + ['\u{a882}','\u{a8b3}'], + ['\u{a8d0}','\u{a8d9}'], + ['\u{a8f2}','\u{a8f7}'], + ['\u{a8fb}','\u{a8fb}'], + ['\u{a900}','\u{a925}'], + ['\u{a930}','\u{a946}'], + ['\u{a960}','\u{a97c}'], + ['\u{a984}','\u{a9b2}'], + ['\u{a9cf}','\u{a9d9}'], + ['\u{aa00}','\u{aa28}'], + ['\u{aa40}','\u{aa42}'], + ['\u{aa44}','\u{aa4b}'], + ['\u{aa50}','\u{aa59}'], + ['\u{aa60}','\u{aa76}'], + ['\u{aa7a}','\u{aa7a}'], + ['\u{aa80}','\u{aaaf}'], + ['\u{aab1}','\u{aab1}'], + ['\u{aab5}','\u{aab6}'], + ['\u{aab9}','\u{aabd}'], + ['\u{aac0}','\u{aac0}'], + ['\u{aac2}','\u{aac2}'], + ['\u{aadb}','\u{aadd}'], + ['\u{aae0}','\u{aaea}'], + ['\u{aaf2}','\u{aaf4}'], + ['\u{ab01}','\u{ab06}'], + ['\u{ab09}','\u{ab0e}'], + ['\u{ab11}','\u{ab16}'], + ['\u{ab20}','\u{ab26}'], + ['\u{ab28}','\u{ab2e}'], + ['\u{abc0}','\u{abe2}'], + ['\u{abf0}','\u{abf9}'], + ['\u{ac00}','\u{d7a3}'], + ['\u{d7b0}','\u{d7c6}'], + ['\u{d7cb}','\u{d7fb}'], + ['\u{f900}','\u{fa6d}'], + ['\u{fa70}','\u{fad9}'], + ['\u{fb00}','\u{fb06}'], + ['\u{fb13}','\u{fb17}'], + ['\u{fb1d}','\u{fb1d}'], + ['\u{fb1f}','\u{fb28}'], + ['\u{fb2a}','\u{fb36}'], + ['\u{fb38}','\u{fb3c}'], + ['\u{fb3e}','\u{fb3e}'], + ['\u{fb40}','\u{fb41}'], + ['\u{fb43}','\u{fb44}'], + ['\u{fb46}','\u{fbb1}'], + ['\u{fbd3}','\u{fd3d}'], + ['\u{fd50}','\u{fd8f}'], + ['\u{fd92}','\u{fdc7}'], + ['\u{fdf0}','\u{fdfb}'], + ['\u{fe70}','\u{fe74}'], + ['\u{fe76}','\u{fefc}'], + ['\u{ff10}','\u{ff19}'], + ['\u{ff21}','\u{ff3a}'], + ['\u{ff41}','\u{ff5a}'], + ['\u{ff66}','\u{ffbe}'], + ['\u{ffc2}','\u{ffc7}'], + ['\u{ffca}','\u{ffcf}'], + ['\u{ffd2}','\u{ffd7}'], + ['\u{ffda}','\u{ffdc}'], + ['\u{10000}','\u{1000b}'], + ['\u{1000d}','\u{10026}'], + ['\u{10028}','\u{1003a}'], + ['\u{1003c}','\u{1003d}'], + ['\u{1003f}','\u{1004d}'], + ['\u{10050}','\u{1005d}'], + ['\u{10080}','\u{100fa}'], + ['\u{10280}','\u{1029c}'], + ['\u{102a0}','\u{102d0}'], + ['\u{10300}','\u{1031e}'], + ['\u{10330}','\u{10340}'], + ['\u{10342}','\u{10349}'], + ['\u{10380}','\u{1039d}'], + ['\u{103a0}','\u{103c3}'], + ['\u{103c8}','\u{103cf}'], + ['\u{10400}','\u{1049d}'], + ['\u{104a0}','\u{104a9}'], + ['\u{10800}','\u{10805}'], + ['\u{10808}','\u{10808}'], + ['\u{1080a}','\u{10835}'], + ['\u{10837}','\u{10838}'], + ['\u{1083c}','\u{1083c}'], + ['\u{1083f}','\u{10855}'], + ['\u{10900}','\u{10915}'], + ['\u{10920}','\u{10939}'], + ['\u{10980}','\u{109b7}'], + ['\u{109be}','\u{109bf}'], + ['\u{10a00}','\u{10a00}'], + ['\u{10a10}','\u{10a13}'], + ['\u{10a15}','\u{10a17}'], + ['\u{10a19}','\u{10a33}'], + ['\u{10a60}','\u{10a7c}'], + ['\u{10b00}','\u{10b35}'], + ['\u{10b40}','\u{10b55}'], + ['\u{10b60}','\u{10b72}'], + ['\u{10c00}','\u{10c48}'], + ['\u{11003}','\u{11037}'], + ['\u{11066}','\u{1106f}'], + ['\u{11083}','\u{110af}'], + ['\u{110d0}','\u{110e8}'], + ['\u{110f0}','\u{110f9}'], + ['\u{11103}','\u{11126}'], + ['\u{11136}','\u{1113f}'], + ['\u{11183}','\u{111b2}'], + ['\u{111c1}','\u{111c4}'], + ['\u{111d0}','\u{111d9}'], + ['\u{11680}','\u{116aa}'], + ['\u{116c0}','\u{116c9}'], + ['\u{12000}','\u{1236e}'], + ['\u{13000}','\u{1342e}'], + ['\u{16800}','\u{16a38}'], + ['\u{16f00}','\u{16f44}'], + ['\u{16f50}','\u{16f50}'], + ['\u{16f93}','\u{16f9f}'], + ['\u{1b000}','\u{1b001}'], + ['\u{1d400}','\u{1d454}'], + ['\u{1d456}','\u{1d49c}'], + ['\u{1d49e}','\u{1d49f}'], + ['\u{1d4a2}','\u{1d4a2}'], + ['\u{1d4a5}','\u{1d4a6}'], + ['\u{1d4a9}','\u{1d4ac}'], + ['\u{1d4ae}','\u{1d4b9}'], + ['\u{1d4bb}','\u{1d4bb}'], + ['\u{1d4bd}','\u{1d4c3}'], + ['\u{1d4c5}','\u{1d505}'], + ['\u{1d507}','\u{1d50a}'], + ['\u{1d50d}','\u{1d514}'], + ['\u{1d516}','\u{1d51c}'], + ['\u{1d51e}','\u{1d539}'], + ['\u{1d53b}','\u{1d53e}'], + ['\u{1d540}','\u{1d544}'], + ['\u{1d546}','\u{1d546}'], + ['\u{1d54a}','\u{1d550}'], + ['\u{1d552}','\u{1d6a5}'], + ['\u{1d6a8}','\u{1d6c0}'], + ['\u{1d6c2}','\u{1d6da}'], + ['\u{1d6dc}','\u{1d6fa}'], + ['\u{1d6fc}','\u{1d714}'], + ['\u{1d716}','\u{1d734}'], + ['\u{1d736}','\u{1d74e}'], + ['\u{1d750}','\u{1d76e}'], + ['\u{1d770}','\u{1d788}'], + ['\u{1d78a}','\u{1d7a8}'], + ['\u{1d7aa}','\u{1d7c2}'], + ['\u{1d7c4}','\u{1d7cb}'], + ['\u{1d7ce}','\u{1d7ff}'], + ['\u{1ee00}','\u{1ee03}'], + ['\u{1ee05}','\u{1ee1f}'], + ['\u{1ee21}','\u{1ee22}'], + ['\u{1ee24}','\u{1ee24}'], + ['\u{1ee27}','\u{1ee27}'], + ['\u{1ee29}','\u{1ee32}'], + ['\u{1ee34}','\u{1ee37}'], + ['\u{1ee39}','\u{1ee39}'], + ['\u{1ee3b}','\u{1ee3b}'], + ['\u{1ee42}','\u{1ee42}'], + ['\u{1ee47}','\u{1ee47}'], + ['\u{1ee49}','\u{1ee49}'], + ['\u{1ee4b}','\u{1ee4b}'], + ['\u{1ee4d}','\u{1ee4f}'], + ['\u{1ee51}','\u{1ee52}'], + ['\u{1ee54}','\u{1ee54}'], + ['\u{1ee57}','\u{1ee57}'], + ['\u{1ee59}','\u{1ee59}'], + ['\u{1ee5b}','\u{1ee5b}'], + ['\u{1ee5d}','\u{1ee5d}'], + ['\u{1ee5f}','\u{1ee5f}'], + ['\u{1ee61}','\u{1ee62}'], + ['\u{1ee64}','\u{1ee64}'], + ['\u{1ee67}','\u{1ee6a}'], + ['\u{1ee6c}','\u{1ee72}'], + ['\u{1ee74}','\u{1ee77}'], + ['\u{1ee79}','\u{1ee7c}'], + ['\u{1ee7e}','\u{1ee7e}'], + ['\u{1ee80}','\u{1ee89}'], + ['\u{1ee8b}','\u{1ee9b}'], + ['\u{1eea1}','\u{1eea3}'], + ['\u{1eea5}','\u{1eea9}'], + ['\u{1eeab}','\u{1eebb}'], + ['\u{20000}','\u{2a6d6}'], + ['\u{2a700}','\u{2b734}'], + ['\u{2b740}','\u{2b81d}'], + ['\u{2f800}','\u{2fa1d}'], +] + +const tabdigit = [ + ['\u{30}','\u{39}'], + ['\u{660}','\u{669}'], + ['\u{6f0}','\u{6f9}'], + ['\u{7c0}','\u{7c9}'], + ['\u{966}','\u{96f}'], + ['\u{9e6}','\u{9ef}'], + ['\u{a66}','\u{a6f}'], + ['\u{ae6}','\u{aef}'], + ['\u{b66}','\u{b6f}'], + ['\u{be6}','\u{bef}'], + ['\u{c66}','\u{c6f}'], + ['\u{ce6}','\u{cef}'], + ['\u{d66}','\u{d6f}'], + ['\u{e50}','\u{e59}'], + ['\u{ed0}','\u{ed9}'], + ['\u{f20}','\u{f29}'], + ['\u{1040}','\u{1049}'], + ['\u{1090}','\u{1099}'], + ['\u{17e0}','\u{17e9}'], + ['\u{1810}','\u{1819}'], + ['\u{1946}','\u{194f}'], + ['\u{19d0}','\u{19d9}'], + ['\u{1a80}','\u{1a89}'], + ['\u{1a90}','\u{1a99}'], + ['\u{1b50}','\u{1b59}'], + ['\u{1bb0}','\u{1bb9}'], + ['\u{1c40}','\u{1c49}'], + ['\u{1c50}','\u{1c59}'], + ['\u{a620}','\u{a629}'], + ['\u{a8d0}','\u{a8d9}'], + ['\u{a900}','\u{a909}'], + ['\u{a9d0}','\u{a9d9}'], + ['\u{aa50}','\u{aa59}'], + ['\u{abf0}','\u{abf9}'], + ['\u{ff10}','\u{ff19}'], + ['\u{104a0}','\u{104a9}'], + ['\u{11066}','\u{1106f}'], + ['\u{110f0}','\u{110f9}'], + ['\u{11136}','\u{1113f}'], + ['\u{111d0}','\u{111d9}'], + ['\u{116c0}','\u{116c9}'], + ['\u{1d7ce}','\u{1d7ff}'], +] + +const tabxdigit = [ + ['\u{30}','\u{39}'], + ['\u{41}','\u{46}'], + ['\u{61}','\u{66}'], +] + +const tabspace = [ + ['\u{9}','\u{d}'], + ['\u{20}','\u{20}'], + ['\u{85}','\u{85}'], + ['\u{a0}','\u{a0}'], + ['\u{1680}','\u{1680}'], + ['\u{2000}','\u{200a}'], + ['\u{2028}','\u{2029}'], + ['\u{202f}','\u{202f}'], + ['\u{205f}','\u{205f}'], + ['\u{3000}','\u{3000}'], +] + +const tabblank = [ + ['\u{9}','\u{9}'], + ['\u{20}','\u{20}'], + ['\u{a0}','\u{a0}'], + ['\u{1680}','\u{1680}'], + ['\u{2000}','\u{200a}'], + ['\u{202f}','\u{202f}'], + ['\u{205f}','\u{205f}'], + ['\u{3000}','\u{3000}'], +] + diff --git a/lib/regex/redump.myr b/lib/regex/redump.myr new file mode 100644 index 0000000..7233864 --- /dev/null +++ b/lib/regex/redump.myr @@ -0,0 +1,87 @@ +use std +use bio +use regex + +const main = {args + var cmd, comp + var verbose + var fd + + verbose = false + cmd = std.optparse(args, &[ + .argdesc = "regex [inputs...]", + .minargs = 1, + .maxargs = 1, + .opts = [ + [.opt='v', .desc="dump verbose regex output"] + ][:], + ]) + for opt in cmd.opts + match opt + | ('v', _): verbose = true + | _: std.fatal("Unknown argument") + ;; + ;; + if verbose + comp = regex.dbgcompile(cmd.args[0]) + else + comp = regex.compile(cmd.args[0]) + ;; + match comp + | `std.Fail m: + std.fatal("unable to compile regex: {}\n", regex.failmsg(m)) + | `std.Ok re: + if cmd.args.len > 1 + runall(re, cmd.args) + else + fd = bio.mkfile(0, bio.Rd) + dump(re, fd) + bio.close(fd) + ;; + ;; +} + +const runall = {re, files + + for f in files + match bio.open(f, bio.Rd) + | `std.Ok fd: + dump(re, fd) + bio.close(fd) + | `std.Fail m: + std.fatal("failed to open {}: {}\n", f, m) + ;; + ;; +} + +const dump = {re, fd + while true + match bio.readln(fd) + | `std.Some ln: + show(re, ln, regex.exec(re, ln)) + std.slfree(ln) + | `std.None: + break + ;; + ;; +} + +const show = {re, ln, mg + var i + + match mg + | `std.Some rl: + std.put("Matched: {}\n", rl[0]) + for i = 1; i < rl.len; i++ + std.put("\tgroup {}: {}\n", i, rl[i]) + ;; + | `std.None: + std.put("Match failed:\n") + std.put("\t{}\n", ln) + std.put("\t") + for i = 0; i < re.strp - 1; i++ + std.put("~") + ;; + std.put("^\n") + ;; +} diff --git a/lib/regex/test/basic.myr b/lib/regex/test/basic.myr new file mode 100644 index 0000000..168b547 --- /dev/null +++ b/lib/regex/test/basic.myr @@ -0,0 +1,39 @@ +use std + +use "testmatch.use" + +const main = { + var s : byte[:] + + s = std.strjoin([ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ][:], "") + testmatch(".*bc", "Abc", `std.Some [][:]) + testmatch("(a*)*", "a", `std.Some ["a"][:]) + testmatch("(aa|aab?)*", s, `std.Some ["aa"][:]) + /* greedy matches */ + testmatch("(<.*>).*", "<a foo> blah <bar>", `std.Some [ + "<a foo> blah <bar>", + ][:]) + testmatch("(<.+>).*", "<a foo> blah <bar>", `std.Some [ + "<a foo> blah <bar>", + ][:]) + /* reluctant matches */ + testmatch("(<.*?>).*", "<a foo> blah <bar>", `std.Some [ + "<a foo>", + ][:]) + testmatch("(<.+?>).*", "<a foo> blah <bar>", `std.Some [ + "<a foo>", + ][:]) +} diff --git a/lib/regex/test/bld.sub b/lib/regex/test/bld.sub new file mode 100644 index 0000000..12f8056 --- /dev/null +++ b/lib/regex/test/bld.sub @@ -0,0 +1,7 @@ +test basic {inc=../libstd,inc=..} = basic.myr testmatch.myr;; +test boundaries {inc=../libstd,inc=..} = boundaries.myr testmatch.myr;; +test capture {inc=../libstd,inc=..} = capture.myr testmatch.myr;; +test class {inc=../libstd,inc=..} = class.myr testmatch.myr;; +test failmatch {inc=../libstd,inc=..} = failmatch.myr testmatch.myr;; +test negclass {inc=../libstd,inc=..} = negclass.myr testmatch.myr;; +test unicode {inc=../libstd,inc=..} = unicode.myr testmatch.myr;; diff --git a/lib/regex/test/boundaries.myr b/lib/regex/test/boundaries.myr new file mode 100644 index 0000000..196d197 --- /dev/null +++ b/lib/regex/test/boundaries.myr @@ -0,0 +1,36 @@ +use std +use "testmatch.use" + +const main = { + /* expected matches */ + testmatch("\\<([a-z]*)\\>", "abcdef", `std.Some [ + "abcdef", + ][:]) + testmatch(".*(\\<.*\\>).*", "!m!", `std.Some [ /* single char word in midstring */ + "m", + ][:]) + testmatch(".*(\\<.*\\>).*", "!m", `std.Some [ /* single char word at end of string */ + "m", + ][:]) + testmatch(".*(\\<.*\\>).*", "m!", `std.Some [ /* single char word at start of string */ + "m", + ][:]) + testmatch(".*(\\<.*\\>).*", "!@#!!matches!!%!", `std.Some [ /* word in midstring */ + "matches", + ][:]) + testmatch(".*(\\<.*\\>).*", "matches!!%!", `std.Some [ /* word at start of string */ + "matches", + ][:]) + testmatch(".*(\\<.*\\>).*", "!@#!!matches", `std.Some [ /* word at end of string */ + "matches", + ][:]) + testmatch(".*(\\<.*\\>).*", "!@#!!matches!!%!foo", `std.Some [ /* matches last word in string */ + "foo", + ][:]) + testmatch(".*(\\<.*\\>).*", "123", `std.Some [ /* numbers are also word bounds */ + "123", + ][:]) + + /* nonmatches */ + testmatch("\\<([a-z]*)\\>foo", "abcdefoo", `std.None) /* word boundary needed in midstring */ +} diff --git a/lib/regex/test/capture.myr b/lib/regex/test/capture.myr new file mode 100644 index 0000000..f270428 --- /dev/null +++ b/lib/regex/test/capture.myr @@ -0,0 +1,17 @@ +use std +use "testmatch.use" + +const main = { + testmatch("A(.*)", "Abc", `std.Some ["bc"][:]) + testmatch("A(.*)e", "Abcde", `std.Some ["bcd"][:]) + testmatch("(a|b)+", "abab", `std.Some ["b"][:]) + testmatch("A(b(.*)d)e", "Abcde", `std.Some [ + "bcd", + "c" + ][:]) + testmatch("(a?)(a*)(a?)", "aaaa", `std.Some [ + "a", + "aaa", + "" + ][:]) +} diff --git a/lib/regex/test/class.myr b/lib/regex/test/class.myr new file mode 100644 index 0000000..284f440 --- /dev/null +++ b/lib/regex/test/class.myr @@ -0,0 +1,67 @@ +use std + +use "testmatch.use" + +const main = { + asciiclass() + set() + /* + unicodeclass() + negasciiclass() + negasciirange() + negset() + */ +} + +const asciiclass = { + /* \d success */ + testmatch("\\d", "1", `std.Some [][:]) + testmatch("\\d\\d", "13", `std.Some [][:]) + testmatch("\\d+", "13688", `std.Some [][:]) + /* \d fail */ + testmatch("\\d", "x", `std.None) + testmatch("\\d\\d", "x3", `std.None) + testmatch("\\d+", "1368f", `std.None) + + /* \x success */ + testmatch("\\x", "a", `std.Some [][:]) + testmatch("\\x\\x", "1F", `std.Some [][:]) + testmatch("\\x+", "13b8cDEf", `std.Some [][:]) + /* \x fail */ + testmatch("\\x", "Z", `std.None) + testmatch("\\x\\x", "fg", `std.None) + testmatch("\\x+", "13b8cg", `std.None) + + /* \s success */ + testmatch("\\s", " ", `std.Some [][:]) + testmatch("\\s\\s", "\t\n", `std.Some [][:]) + testmatch("\\s+", "\t\n\r \t", `std.Some [][:]) + /* \s fail */ + testmatch("\\s", "a", `std.None) + testmatch("\\s\\s", "i\n", `std.None) + testmatch("\\s+", "\t\n\r.\t", `std.None) + + /* word success */ + testmatch("\\w+", "abcABC0123_", `std.Some [][:]) + /* word fail */ + testmatch("\\w+", "abcABC0123_.", `std.None) + + /* \h success */ + testmatch("\\h", " ", `std.Some [][:]) + testmatch("\\h\\h", "\t ", `std.Some [][:]) + testmatch("\\h+", "\t \t ", `std.Some [][:]) + /* \h fail */ + testmatch("\\h", "\n", `std.None) + testmatch("\\h\\h", "\t\r", `std.None) + testmatch("\\h+", "\t \t.", `std.None) +} + +const set = { + /* ranges */ + testmatch("[a-z]*", "abcd", `std.Some [][:]) + testmatch("[a-zA-Z]*", "abCD", `std.Some [][:]) + testmatch("[a-zA-Z0-9_]*", "_abCD018", `std.Some [][:]) + + testmatch("[abc]*", "abba", `std.Some [][:]) + testmatch("[a-zABC]*", "abBa", `std.Some [][:]) +} diff --git a/lib/regex/test/failmatch.myr b/lib/regex/test/failmatch.myr new file mode 100644 index 0000000..c501d00 --- /dev/null +++ b/lib/regex/test/failmatch.myr @@ -0,0 +1,7 @@ +use std + +use "testmatch.use" + +const main = { + testmatch(".*bcd", "Abc", `std.None) +} diff --git a/lib/regex/test/negclass.myr b/lib/regex/test/negclass.myr new file mode 100644 index 0000000..19404fa --- /dev/null +++ b/lib/regex/test/negclass.myr @@ -0,0 +1,72 @@ +use std + +use "testmatch.use" + +const main = { + asciiclass() + set() + /* + unicodeclass() + negasciiclass() + negasciirange() + negset() + */ +} + +const asciiclass = { + /* \D success */ + testmatch("\\D", "x", `std.Some [][:]) + testmatch("\\D+", "xa!#^cs", `std.Some [][:]) + + /* \D fail: end of ranges chars */ + testmatch("\\D", "0", `std.None) + testmatch("\\D", "9", `std.None) + testmatch("\\D+", "a35x", `std.None) + testmatch("\\D+", "13688", `std.None) + + /* \X success */ + testmatch("\\X", "Z", `std.Some [][:]) + testmatch("\\X\\X", "gg", `std.Some [][:]) + /* \X fail */ + testmatch("\\X", "a", `std.None) + testmatch("\\X+", "zz13b8cDEf", `std.None) + + /* \S success */ + testmatch("\\S", "a", `std.Some [][:]) + testmatch("\\S\\S", "i%", `std.Some [][:]) + testmatch("\\S+", "alskd690!#!!", `std.Some [][:]) + + /* \S fail */ + testmatch("\\S", " ", `std.None) + testmatch("\\S\\S", "\t\n", `std.None) + testmatch("\\S+", "\t \nkait", `std.None) + + /* word success */ + testmatch("\\W+", "!%!^^@@!^", `std.Some [][:]) + /* word fail */ + testmatch("\\W+", "a^#$bcABC0123_", `std.None) + + /* \H success */ + testmatch("\\H", "\n", `std.Some [][:]) + testmatch("\\H\\H", "\n\r", `std.Some [][:]) + /* \H fail */ + testmatch("\\H+", "\t \t.", `std.None) + testmatch("\\H\\H", "\t ", `std.None) + testmatch("\\H+", "\ta35 \t ", `std.None) +} + +const set = { + /* ranges: should succeed */ + testmatch("[^a-z]*", "ABCD", `std.Some [][:]) + testmatch("[^a-zA-Z]*", "1234", `std.Some [][:]) + testmatch("[^a-zA-Z0-9_]*", "-^^-", `std.Some [][:]) + testmatch("[^abc]*", "d6d", `std.Some [][:]) + testmatch("[^a-zABC]*", "!^!!))#", `std.Some [][:]) + + /* ranges: should fail */ + testmatch("[^a-z]*", "abcd", `std.None) + testmatch("[^a-zA-Z]*", "abCD", `std.None) + testmatch("[^a-zA-Z0-9_]*", "_abCD018", `std.None) + testmatch("[^abc]*", "abba", `std.None) + testmatch("[^a-zABC]*", "abBa", `std.None) +} diff --git a/lib/regex/test/runtest.sh b/lib/regex/test/runtest.sh new file mode 100755 index 0000000..95f548f --- /dev/null +++ b/lib/regex/test/runtest.sh @@ -0,0 +1,124 @@ +#!/bin/bash +NFAILURES=0 +NPASSES=0 + +function build { + rm -f $1 $1.o $1.s $1.use + myrbuild $FLAGS -b $1 $1.myr $EXTRA_SRC +} + +function pass { + PASSED="$PASSED $1" + NPASSED=$[$NPASSED + 1] +} + +function fail { + echo "FAIL: $1" + FAILED="$FAILED $1" + NFAILED=$[$NFAILED + 1] +} + +function expectstatus { + ./$1 $3 + if [ $? -eq $2 ]; then + pass $1 + return + else + fail $1 + fi +} + +function expectprint { + if [ "`./$1 $3`" != "$2" ]; then + fail $1 + else + pass $1 + fi +} + + +function expectcompare { + if [ x"" != x"$TMPDIR" ]; then + t=$TMPDIR/myrtest-$1-$RANDOM + else + t=/tmp/myrtest-$1-$RANDOM + fi + ./$1 $3 > $t + if cmp $t data/$1-expected; then + pass $1 + else + fail $1 + fi + rm -f $t +} + +function expectfcompare { + ./$1 $3 + if cmp data/$1-expected $2; then + pass $1 + else + fail $1 + fi +} + +function shouldskip { + if [ -z $ARGS ]; then + return 1 + fi + + for i in $ARGS; do + if [ $i = $1 ]; then + return 1 + fi + done + return 0 +} + + +# Should build and run +function B { + if shouldskip $1; then + return + fi + + test="$1"; shift + type="$1"; shift + res="$1"; shift + if [ $# > 0 ]; then + args="$1"; shift + fi + build $test + case $type in + "E") expectstatus "$test" "$res" "$input";; + "P") expectprint "$test" "$res" "$input";; + "C") expectcompare "$test" "$res" "$input";; + "F") expectfcompare "$test" "$res" "$args";; + esac +} + +# Should fail +function F { + if shouldskip $1; then + return + fi + (build $1) > /dev/null + if [ $? -eq '1' ]; then + pass $1 + else + fail $1 + fi +} + +# Should generate a usefile +function U { + return +} + +source tests + +echo "PASSED ($NPASSED): $PASSED" +if [ -z "$NFAILED" ]; then + echo "SUCCESS" +else + echo "FAILURES ($NFAILED): $FAILED" +fi diff --git a/lib/regex/test/testmatch.myr b/lib/regex/test/testmatch.myr new file mode 100644 index 0000000..4600410 --- /dev/null +++ b/lib/regex/test/testmatch.myr @@ -0,0 +1,58 @@ +use std +use regex + +pkg = + const testmatch : (pat : byte[:], text : byte[:], expected : std.option(byte[:][:]) -> void) + const dbgmatch : (pat : byte[:], text : byte[:], expected : std.option(byte[:][:]) -> void) +;; + +const testmatch = {pat, text, expected + run(regex.compile(pat), pat, text, expected) +} + +const dbgmatch = {pat, text, expected + run(regex.dbgcompile(pat), pat, text, expected) +} + +const run = {regex, pat, text, expected + var i, re + + re = std.try(regex) + match regex.exec(re, text) + | `std.Some res: + match expected + | `std.None: + std.fatal("expected no match, got:") + for i = 0; i < res.len; i++ + std.put("\t{}: {}\n", i, res[i]) + ;; + | `std.Some exp: + if !std.sleq(res[0], text) + std.put("whole match does not match text!\n") + std.fatal("failed matching {} over {}\n", pat, text) + ;; + res = res[1:] + if res.len != exp.len + std.put("mismatch: expected {} matches, got {}\n", exp.len, res.len) + std.fatal("failed matching {} over {}\n", pat, text) + ;; + for i = 0; i < exp.len; i++ + if !std.sleq(res[i], exp[i]) + std.put("mismatch on {}: expected {}, got {}\n", i, exp[i], res[i]) + std.fatal("failed matching {} over {}\n", pat, text) + ;; + ;; + ;; + | `std.None: + match expected + | `std.None: /* : expected failure */ + | `std.Some matches: + std.put("expected matches:\n") + for i = 0; i < matches.len; i++ + std.put("\t{}: {}\n", i, matches[i]) + ;; + std.fatal("no match found\n") + ;; + ;; + regex.free(re) +} diff --git a/lib/regex/test/tests b/lib/regex/test/tests new file mode 100644 index 0000000..a5f70f7 --- /dev/null +++ b/lib/regex/test/tests @@ -0,0 +1,29 @@ +FLAGS=-I../ +EXTRA_SRC=testmatch.myr +# Format: +# [B|F] testname [E|P] result +# [B|F]: Compiler outcome. +# B: Expect that this test will build. +# F: Expect that this test will not build. +# testname: Test case +# The test that will run. We will try to +# compile 'testname.myr' to 'testname', +# and then execute it, verifying the result +# [E|P|C]: Result type +# E tells us that the result is an exit status +# P tells us that the result is on stdout, +# and should be compared to the value on the +# line +# C tells us that the result is on stdout, +# and should be compared to the contents of +# the file passed on the line. +# result: Result value +# What we compare with. This should be self- +# evident. +B basic C +B boundaries C +B capture C +B class C +B failmatch C +B negclass C +B unicode C diff --git a/lib/regex/test/unicode.myr b/lib/regex/test/unicode.myr new file mode 100644 index 0000000..5916a1c --- /dev/null +++ b/lib/regex/test/unicode.myr @@ -0,0 +1,19 @@ +use std +use regex + +use "testmatch.use" + +const main = { + testmatch(".*bæc", "Abæc", `std.Some [][:]) + testmatch("(\\p{L}*)bæc\\P{L}*", \ + "Aabæc%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", \ + `std.Some ["Aa"][:]) + /* test various syntaxen */ + testmatch("(\\pL*)bæc\\PL*", \ + "Aabæc%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", \ + `std.Some ["Aa"][:]) + testmatch("(\\p{Letter}*)bæc\\P{Uppercase_Letter}*", \ + "Aabæc%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", \ + `std.Some ["Aa"][:]) + testmatch(".", "æ", `std.Some [][:]) +} diff --git a/lib/regex/types.myr b/lib/regex/types.myr new file mode 100644 index 0000000..b283d2a --- /dev/null +++ b/lib/regex/types.myr @@ -0,0 +1,88 @@ +use std + +pkg regex = + type status = union + `Noimpl + `Incomplete + `Unbalanced + `Emptyparen + `Badrep + `Badrange + `Badescape + ;; + + type ast = union + /* basic string building */ + `Alt (ast#, ast#) + `Cat (ast#, ast#) + + /* repetition */ + `Star ast# + `Rstar ast# + `Plus ast# + `Rplus ast# + `Quest ast# + + /* end matches */ + `Chr char + `Ranges char[2][:] + + /* meta */ + `Cap (std.size, ast#) /* id, ast */ + `Bol /* beginning of line */ + `Eol /* end of line */ + `Bow /* beginning of word */ + `Eow /* end of word */ + ;; + + + type regex = struct + /* compile state */ + debug : bool + pat : byte[:] + nmatch : std.size + + /* VM state */ + runq : rethread# + expired : rethread# + expiredtail : rethread# + proglen : std.size + prog : reinst[:] + nthr : std.size + str : byte[:] + strp : std.size + ;; + + type rethread = struct + next : rethread# /* run queue link */ + + tid : std.size /* just for debugging */ + ip : std.size /* the instruction pointer */ + dead : bool /* thread died */ + matched : bool /* thread matched */ + + mstart : std.size[:] /* match starts */ + mend : std.size[:] /* match ends */ + ;; + + pkglocal type reinst = union + /* direct consumers */ + `Ibyte byte + `Irange (byte, byte) + + /* groups */ + `Ilbra std.size + `Irbra std.size + + /* anchors */ + `Ibol + `Ieol + `Ibow + `Ieow + + /* control flow */ + `Ifork (std.size, std.size) + `Ijmp std.size + `Imatch std.size + ;; +;; diff --git a/lib/std/alloc.myr b/lib/std/alloc.myr new file mode 100644 index 0000000..ed3b023 --- /dev/null +++ b/lib/std/alloc.myr @@ -0,0 +1,423 @@ +use "die.use" +use "extremum.use" +use "types.use" +use "units.use" +use "syswrap.use" + +/* +The allocator implementation here is based on Bonwick's slab allocator. + +For small allocations (up to Bktmax), it works by requesting large, +power of two aligned chunks from the operating system, and breaking +them into a linked list of equal sized chunks. Allocations are then +satisfied by taking the head of the list of chunks. Empty slabs +are removed from the freelist. + +The data structure looks something like this: + Bkts: + [16 byte] -> [slab hdr | chunk -> chunk -> chunk] -> [slab hdr | chunk -> chunk -> chunk] + [32 byte] -> Zslab + [64 byte] -> [slab hdr | chunk -> chunk] + ... + [32k byte] -> ... + +Large allocations are simply satisfied by mmap(). + +*/ + +pkg std = + generic alloc : ( -> @a#) + generic zalloc : ( -> @a#) + generic free : (v:@a# -> void) + + generic slalloc : (len : size -> @a[:]) + generic slzalloc : (len : size -> @a[:]) + generic slgrow : (sl : @a[:], len : size -> @a[:]) + generic slzgrow : (sl : @a[:], len : size -> @a[:]) + generic slfree : (sl : @a[:] -> void) + + const bytealloc : (sz:size -> byte#) + const zbytealloc : (sz:size -> byte#) + const bytefree : (m:byte#, sz:size -> void) + + +;; + +/* null pointers. only used internally. */ +const Zslab = 0 castto(slab#) +const Zchunk = 0 castto(chunk#) + +const Slabsz = 1*MiB /* 1 meg slabs */ +const Cachemax = 16 /* maximum number of slabs in the cache */ +const Bktmax = 32*KiB /* Slabsz / 8; a balance. */ +const Pagesz = 4*KiB +const Align = 16 /* minimum allocation alignment */ + +var buckets : bucket[32] /* excessive */ + +type slheader = struct + cap : size /* capacity in bytes */ + magic : size /* magic check value */ +;; + +type bucket = struct + sz : size /* aligned size */ + nper : size /* max number of elements per slab */ + slabs : slab# /* partially filled or free slabs */ + cache : slab# /* cache of empty slabs, to prevent thrashing */ + ncache : size /* size of cache */ +;; + +type slab = struct + head : byte# /* head of virtual addresses, so we don't leak address space */ + next : slab# /* the next slab on the chain */ + freehd : chunk# /* the nodes we're allocating */ + nfree : size /* the number of free nodes */ +;; + +type chunk = struct /* NB: must be smaller than sizeof(slab) */ + next : chunk# /* the next chunk in the free list */ +;; + +const __init__ = { + var i + + for i = 0; i < buckets.len && (Align << i) <= Bktmax; i++ + bktinit(&buckets[i], Align << i) + ;; +} + +/* Allocates an object of type @a, returning a pointer to it. */ +generic alloc = {-> @a# + -> bytealloc(sizeof(@a)) castto(@a#) +} + +generic zalloc = {-> @a# + -> zbytealloc(sizeof(@a)) castto(@a#) +} + +/* Frees a value of type @a */ +generic free = {v:@a# -> void + bytefree(v castto(byte#), sizeof(@a)) +} + +/* allocates a slice of 'len' elements. */ +generic slalloc = {len + var p, sz + + if len == 0 + -> [][:] + ;; + sz = len*sizeof(@a) + align(sizeof(slheader), Align) + p = bytealloc(sz) + p = inithdr(p, sz) + -> (p castto(@a#))[0:len] +} + +generic slzalloc = {len + var p, sz + + if len == 0 + -> [][:] + ;; + sz = len*sizeof(@a) + align(sizeof(slheader), Align) + p = zbytealloc(sz) + p = inithdr(p, sz) + -> (p castto(@a#))[0:len] +} + +const inithdr = {p, sz + var phdr, prest + + phdr = p castto(slheader#) + phdr.cap = allocsz(sz) - align(sizeof(slheader), Align) + phdr.magic = (0xdeadbeefbadf00d castto(size)) + + prest = (p castto(size)) + align(sizeof(slheader), Align) + -> prest castto(byte#) +} + +const checkhdr = {p + var phdr, addr + + addr = p castto(size) + addr -= align(sizeof(slheader), Align) + phdr = addr castto(slheader#) + assert(phdr.magic == (0xdeadbeefbadf00d castto(size)), "corrupt memory\n") +} + +/* Frees a slice */ +generic slfree = {sl + var head + + if sl.len == 0 + -> + ;; + + checkhdr(sl castto(byte#)) + head = (sl castto(byte#)) castto(size) + head -= align(sizeof(slheader), Align) + bytefree(head castto(byte#), slcap(sl castto(byte#))) +} + +/* Grows a slice */ +generic slgrow = {sl : @a[:], len + var i, n + var new + + /* if the slice doesn't need a bigger bucket, we don't need to realloc. */ + if sl.len > 0 && slcap(sl castto(byte#)) >= allocsz(len*sizeof(@a)) + -> (sl castto(@a#))[:len] + ;; + + new = slalloc(len) + n = min(len, sl.len) + for i = 0; i < n; i++ + new[i] = sl[i] + ;; + if sl.len > 0 + slfree(sl) + ;; + -> new +} + +/* Grows a slice, filling new entries with zero bytes */ +generic slzgrow = {sl : @a[:], len + var oldsz + + oldsz = sl.len*sizeof(@a) + sl = slgrow(sl, len) + zfill((sl castto(byte#))[oldsz:len*sizeof(@a)]) + -> sl +} + +const slcap = {p + var phdr + + phdr = (p castto(size)) - align(sizeof(slheader), Align) castto(slheader#) + -> phdr.cap +} + +const zbytealloc = {sz + var p + + p = bytealloc(sz) + zfill(p[0:sz]) + -> p +} + +const zfill = {sl + var i + + for i = 0; i < sl.len; i++ + sl[i] = 0 + ;; +} + +/* Allocates a blob that is 'sz' bytes long. Dies if the allocation fails */ +const bytealloc = {sz + var bkt, p + + if (sz <= Bktmax) + bkt = &buckets[bktnum(sz)] + p = bktalloc(bkt) + else + p = getmem(sz) + if p == Failmem + die("could not get memory\n") + ;; + ;; + -> p +} + +/* frees a blob that is 'sz' bytes long. */ +const bytefree = {p, sz + var bkt + var b, i + + b = p[:sz] + for i = 0; i < sz; i++ + b[i] = 0xa8 + ;; + if (sz < Bktmax) + bkt = &buckets[bktnum(sz)] + bktfree(bkt, p) + else + freemem(p, sz) + ;; +} + +/* Sets up a single empty bucket */ +const bktinit = {b, sz + b.sz = align(sz, Align) + b.nper = (Slabsz - sizeof(slab))/b.sz + b.slabs = Zslab + b.cache = Zslab + b.ncache = 0 +} + +/* Creates a slab for bucket 'bkt', and fills the chunk list */ +const mkslab = {bkt + var i, p, s + var b, bnext + var off /* offset of chunk head */ + + if bkt.ncache > 0 + s = bkt.cache + bkt.cache = s.next + bkt.ncache-- + ;; + /* + tricky: we need power of two alignment, so we allocate double the + needed size, chop off the unaligned ends, and waste the address + space. Since the OS is "smart enough", this shouldn't actually + cost us memory, and 64 bits of address space means that we're not + going to have issues with running out of address space for a + while. On a 32 bit system this would be a bad idea. + */ + p = getmem(Slabsz*2) + if p == Failmem + die("Unable to mmap") + ;; + + s = align(p castto(size), Slabsz) castto(slab#) + s.head = p + s.nfree = bkt.nper + /* skip past the slab header */ + off = align(sizeof(slab), Align) + bnext = nextchunk(s castto(chunk#), off) + s.freehd = bnext + for i = 0; i < bkt.nper; i++ + b = bnext + bnext = nextchunk(b, bkt.sz) + b.next = bnext + ;; + b.next = Zchunk + -> s +} + +/* +Allocates a node from bucket 'bkt', crashing if the +allocation cannot be satisfied. Will create a new slab +if there are no slabs on the freelist. +*/ +const bktalloc = {bkt + var s + var b + + /* find a slab */ + s = bkt.slabs + if s == Zslab + s = mkslab(bkt) + if s == Zslab + die("No memory left") + ;; + bkt.slabs = s + ;; + + /* grab the first chunk on the slab */ + b = s.freehd + s.freehd = b.next + s.nfree-- + if s.nfree == 0 + bkt.slabs = s.next + s.next = Zslab + ;; + + -> b castto(byte#) +} + +/* +Frees a chunk of memory 'm' into bucket 'bkt'. +Assumes that the memory already came from a slab +that was created for bucket 'bkt'. Will crash +if this is not the case. +*/ +const bktfree = {bkt, m + var s, b + + s = mtrunc(m, Slabsz) castto(slab#) + b = m castto(chunk#) + if s.nfree == 0 + s.next = bkt.slabs + bkt.slabs = s + elif s.nfree == bkt.nper + /* + HACK HACK HACK: if we can't unmap, keep an infinite cache per slab size. + We should solve this better somehow. + */ + if bkt.ncache < Cachemax || !Canunmap + s.next = bkt.cache + bkt.cache = s + else + /* we mapped 2*Slabsz so we could align it, + so we need to unmap the same */ + freemem(s.head, Slabsz*2) + ;; + ;; + s.nfree++ + b.next = s.freehd + s.freehd = b +} + +/* +Finds the correct bucket index to allocate from +for allocations of size 'sz' +*/ +const bktnum = {sz + var i, bktsz + + bktsz = Align + for i = 0; bktsz <= Bktmax; i++ + if bktsz >= sz + -> i + ;; + bktsz *= 2 + ;; + die("Size does not match any buckets") +} + +/* +returns the actual size we allocated for a given +size request +*/ +const allocsz = {sz + var i, bktsz + + if sz <= Bktmax + bktsz = Align + for i = 0; bktsz <= Bktmax; i++ + if bktsz >= sz + -> bktsz + ;; + bktsz *= 2 + ;; + else + -> align(sz, Pagesz) + ;; + die("Size does not match any buckets") +} + +/* +aligns a size to a requested alignment. +'align' must be a power of two +*/ +const align = {v, align + -> (v + align - 1) & ~(align - 1) +} + +/* +chunks are variable sizes, so we can't just +index to get to the next one +*/ +const nextchunk = {b, sz : size + -> ((b castto(intptr)) + (sz castto(intptr))) castto(chunk#) +} + +/* +truncates a pointer to 'align'. 'align' must +be a power of two. +*/ +const mtrunc = {m, align + -> ((m castto(intptr)) & ~((align castto(intptr)) - 1)) castto(byte#) +} diff --git a/lib/std/bigint.myr b/lib/std/bigint.myr new file mode 100644 index 0000000..719fd69 --- /dev/null +++ b/lib/std/bigint.myr @@ -0,0 +1,742 @@ +use "alloc.use" +use "chartype.use" +use "cmp.use" +use "die.use" +use "extremum.use" +use "hasprefix.use" +use "option.use" +use "slcp.use" +use "sldup.use" +use "slfill.use" +use "slpush.use" +use "types.use" +use "utf.use" +use "errno.use" + +pkg std = + type bigint = struct + dig : uint32[:] /* little endian, no leading zeros. */ + sign : int /* -1 for -ve, 0 for zero, 1 for +ve. */ + ;; + + /* administrivia */ + generic mkbigint : (v : @a::(numeric,integral) -> bigint#) + const bigfree : (a : bigint# -> void) + const bigdup : (a : bigint# -> bigint#) + const bigassign : (d : bigint#, s : bigint# -> bigint#) + const bigmove : (d : bigint#, s : bigint# -> bigint#) + const bigparse : (s : byte[:] -> option(bigint#)) + const bigclear : (a : bigint# -> bigint#) + const bigbfmt : (b : byte[:], a : bigint#, base : int -> size) + /* + const bigtoint : (a : bigint# -> @a::(numeric,integral)) + */ + + /* some useful predicates */ + const bigiszero : (a : bigint# -> bool) + const bigeq : (a : bigint#, b : bigint# -> bool) + generic bigeqi : (a : bigint#, b : @a::(numeric,integral) -> bool) + const bigcmp : (a : bigint#, b : bigint# -> order) + + /* bigint*bigint -> bigint ops */ + const bigadd : (a : bigint#, b : bigint# -> bigint#) + const bigsub : (a : bigint#, b : bigint# -> bigint#) + const bigmul : (a : bigint#, b : bigint# -> bigint#) + const bigdiv : (a : bigint#, b : bigint# -> bigint#) + const bigmod : (a : bigint#, b : bigint# -> bigint#) + const bigdivmod : (a : bigint#, b : bigint# -> (bigint#, bigint#)) + const bigshl : (a : bigint#, b : bigint# -> bigint#) + const bigshr : (a : bigint#, b : bigint# -> bigint#) + const bigmodpow : (b : bigint#, e : bigint#, m : bigint# -> bigint#) + /* + const bigpow : (a : bigint#, b : bigint# -> bigint#) + */ + + /* bigint*int -> bigint ops */ + generic bigaddi : (a : bigint#, b : @a::(integral,numeric) -> bigint#) + generic bigsubi : (a : bigint#, b : @a::(integral,numeric) -> bigint#) + generic bigmuli : (a : bigint#, b : @a::(integral,numeric) -> bigint#) + generic bigdivi : (a : bigint#, b : @a::(integral,numeric) -> bigint#) + generic bigshli : (a : bigint#, b : @a::(integral,numeric) -> bigint#) + generic bigshri : (a : bigint#, b : @a::(integral,numeric) -> bigint#) + /* + const bigpowi : (a : bigint#, b : uint64 -> bigint#) + */ +;; + +const Base = 0x100000000ul +generic mkbigint = {v : @a::(integral,numeric) + var a + var val + + a = zalloc() + + if v < 0 + a.sign = -1 + v = -v + elif v > 0 + a.sign = 1 + ;; + val = v castto(uint64) + a.dig = slpush([][:], val castto(uint32)) + if val > Base + a.dig = slpush(a.dig, (val/Base) castto(uint32)) + ;; + -> trim(a) +} + +const bigfree = {a + slfree(a.dig) + free(a) +} + +const bigdup = {a + -> bigassign(zalloc(), a) +} + +const bigassign = {d, s + slfree(d.dig) + d# = s# + d.dig = sldup(s.dig) + -> d +} + +const bigmove = {d, s + slfree(d.dig) + d# = s# + s.dig = [][:] + s.sign = 0 + -> d +} + +const bigclear = {v + std.slfree(v.dig) + v.sign = 0 + v.dig = [][:] + -> v +} + +/* for now, just dump out something for debugging... */ +const bigbfmt = {buf, x, base + const digitchars = [ + '0','1','2','3','4','5','6','7','8','9', + 'a','b','c','d','e','f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z'] + var v, val + var n, i + var tmp, rem, b + + if base < 0 || base > 36 + die("invalid base in bigbfmt\n") + ;; + + if bigiszero(x) + n + ;; + + if base == 0 + b = mkbigint(10) + else + b = mkbigint(base) + ;; + n = 0 + val = bigdup(x) + /* generate the digits in reverse order */ + while !bigiszero(val) + (v, rem) = bigdivmod(val, b) + if rem.dig.len > 0 + n += encode(buf[n:], digitchars[rem.dig[0]]) + else + n += encode(buf[n:], '0') + ;; + bigfree(val) + bigfree(rem) + val = v + ;; + bigfree(val) + bigfree(b) + + /* this is done last, so we get things right when we reverse the string */ + if x.sign == 0 + n += encode(buf[n:], '0') + elif x.sign == -1 + n += encode(buf[n:], '-') + ;; + + /* we only generated ascii digits, so this works for reversing. */ + for i = 0; i < n/2; i++ + tmp = buf[i] + buf[i] = buf[n - i - 1] + buf[n - i - 1] = tmp + ;; + -> n +} + +const bigparse = {str + var c, val : int, base + var v, b + var a + + if hasprefix(str, "0x") || hasprefix(str, "0X") + base = 16 + elif hasprefix(str, "0o") || hasprefix(str, "0O") + base = 8 + elif hasprefix(str, "0b") || hasprefix(str, "0B") + base = 2 + else + base = 10 + ;; + if base != 10 + str = str[2:] + ;; + + a = mkbigint(0) + b = mkbigint(base) + /* + efficiency hack: to save allocations, + just mutate v[0]. The value will always + fit in one digit. + */ + v = mkbigint(1) + while str.len != 0 + (c, str) = striter(str) + if c == '_' + continue + ;; + val = charval(c, base) + if val < 0 || val > base + bigfree(a) + bigfree(b) + bigfree(v) + -> `None + ;; + v.dig[0] = val castto(uint32) + if val == 0 + v.sign = 0 + else + v.sign = 1 + ;; + bigmul(a, b) + bigadd(a, v) + + ;; + -> `Some a +} + +const bigiszero = {v + -> v.dig.len == 0 +} + +const bigeq = {a, b + var i + + if a.sign != b.sign || a.dig.len != b.dig.len + -> false + ;; + for i = 0; i < a.dig.len; i++ + if a.dig[i] != b.dig[i] + -> false + ;; + ;; + -> true +} + +generic bigeqi = {a, b + var v + var dig : uint32[2] + + bigdigit(&v, b < 0, b castto(uint64), dig[:]) + -> bigeq(a, &v) +} + +const bigcmp = {a, b + var i + var da, db, sa, sb + + sa = a.sign castto(int64) + sb = b.sign castto(int64) + if sa < sb + -> `Before + elif sa > sb + -> `After + elif a.dig.len < b.dig.len + -> signedorder(-sa) + elif a.dig.len > b.dig.len + -> signedorder(sa) + else + /* otherwise, the one with the first larger digit is bigger */ + for i = a.dig.len; i > 0; i-- + da = a.dig[i - 1] castto(int64) + db = b.dig[i - 1] castto(int64) + -> signedorder(sa * (da - db)) + ;; + ;; + -> `Equal +} + +const signedorder = {sign + if sign < 0 + -> `Before + elif sign == 0 + -> `Equal + else + -> `After + ;; +} + +/* a += b */ +const bigadd = {a, b + if a.sign == b.sign || a.sign == 0 + a.sign = b.sign + -> uadd(a, b) + elif b.sign == 0 + -> a + else + match bigcmp(a, b) + | `Before: /* a is negative */ + a.sign = b.sign + -> usub(b, a) + | `After: /* b is negative */ + -> usub(a, b) + | `Equal: + die("Impossible. Equal vals with different sign.") + ;; + ;; +} + +/* adds two unsigned values together. */ +const uadd = {a, b + var v, i + var carry + var n + + carry = 0 + n = max(a.dig.len, b.dig.len) + /* guaranteed to carry no more than one value */ + a.dig = slzgrow(a.dig, n + 1) + for i = 0; i < n; i++ + v = (a.dig[i] castto(uint64)) + carry; + if i < b.dig.len + v += (b.dig[i] castto(uint64)) + ;; + + if v >= Base + carry = 1 + else + carry = 0 + ;; + a.dig[i] = v castto(uint32) + ;; + a.dig[i] += carry castto(uint32) + -> trim(a) +} + +/* a -= b */ +const bigsub = {a, b + /* 0 - x = -x */ + if a.sign == 0 + bigassign(a, b) + a.sign = -b.sign + -> a + /* x - 0 = x */ + elif b.sign == 0 + -> a + elif a.sign != b.sign + -> uadd(a, b) + else + match bigcmp(a, b) + | `Before: /* a is negative */ + a.sign = b.sign + -> usub(b, a) + | `After: /* b is negative */ + -> usub(a, b) + | `Equal: + -> bigclear(a) + ;; + ;; + -> a +} + +/* subtracts two unsigned values, where 'a' is strictly greater than 'b' */ +const usub = {a, b + var carry + var v, i + + carry = 0 + for i = 0; i < a.dig.len; i++ + v = (a.dig[i] castto(int64)) - carry + if i < b.dig.len + v -= (b.dig[i] castto(int64)) + ;; + if v < 0 + carry = 1 + else + carry = 0 + ;; + a.dig[i] = v castto(uint32) + ;; + -> trim(a) +} + +/* a *= b */ +const bigmul = {a, b + var i, j + var ai, bj, wij + var carry, t + var w + + if a.sign == 0 || b.sign == 0 + a.sign = 0 + slfree(a.dig) + a.dig = [][:] + -> a + elif a.sign != b.sign + a.sign = -1 + else + a.sign = 1 + ;; + w = slzalloc(a.dig.len + b.dig.len) + for j = 0; j < b.dig.len; j++ + carry = 0 + for i = 0; i < a.dig.len; i++ + ai = a.dig[i] castto(uint64) + bj = b.dig[j] castto(uint64) + wij = w[i+j] castto(uint64) + t = ai * bj + wij + carry + w[i + j] = (t castto(uint32)) + carry = t >> 32 + ;; + w[i+j] = carry castto(uint32) + ;; + slfree(a.dig) + a.dig = w + -> trim(a) +} + +const bigdiv = {a : bigint#, b : bigint# -> bigint# + var q, r + + (q, r) = bigdivmod(a, b) + bigfree(r) + -> bigmove(a, q) +} +const bigmod = {a : bigint#, b : bigint# -> bigint# + var q, r + + (q, r) = bigdivmod(a, b) + bigfree(q) + -> bigmove(a, r) +} + +/* a /= b */ +const bigdivmod = {a : bigint#, b : bigint# -> (bigint#, bigint#) + /* + Implements bigint division using Algorithm D from + Knuth: Seminumerical algorithms, Section 4.3.1. + */ + var m : int64, n : int64 + var qhat, rhat, carry, shift + var x, y, z, w, p, t /* temporaries */ + var b0, aj + var u, v + var i, j : int64 + var q + + if bigiszero(b) + die("divide by zero\n") + ;; + /* if b > a, we trucate to 0, with remainder 'a' */ + if a.dig.len < b.dig.len + -> (mkbigint(0), bigdup(a)) + ;; + + q = zalloc() + q.dig = slzalloc(max(a.dig.len, b.dig.len) + 1) + if a.sign != b.sign + q.sign = -1 + else + q.sign = 1 + ;; + + /* handle single digit divisor separately: the knuth algorithm needs at least 2 digits. */ + if b.dig.len == 1 + carry = 0 + b0 = (b.dig[0] castto(uint64)) + for j = a.dig.len; j > 0; j-- + aj = (a.dig[j - 1] castto(uint64)) + q.dig[j - 1] = (((carry << 32) + aj)/b0) castto(uint32) + carry = (carry << 32) + aj - (q.dig[j-1] castto(uint64))*b0 + ;; + q = trim(q) + -> (q, trim(mkbigint(carry castto(int32)))) + ;; + + u = bigdup(a) + v = bigdup(b) + m = u.dig.len + n = v.dig.len + + shift = nlz(v.dig[n - 1]) + bigshli(u, shift) + bigshli(v, shift) + u.dig = slzgrow(u.dig, u.dig.len + 1) + + for j = m - n; j >= 0; j-- + /* load a few temps */ + x = u.dig[j + n] castto(uint64) + y = u.dig[j + n - 1] castto(uint64) + z = v.dig[n - 1] castto(uint64) + w = v.dig[n - 2] castto(uint64) + t = u.dig[j + n - 2] castto(uint64) + + /* estimate qhat */ + qhat = (x*Base + y)/z + rhat = (x*Base + y) - qhat*z +:divagain + if qhat >= Base || (qhat * w) > (rhat*Base + t) + qhat-- + rhat += z + if rhat < Base + goto divagain + ;; + ;; + + /* multiply and subtract */ + carry = 0 + for i = 0; i < n; i++ + p = qhat * (v.dig[i] castto(uint64)) + + t = (u.dig[i+j] castto(uint64)) - carry - (p % Base) + u.dig[i+j] = t castto(uint32) + + carry = (((p castto(int64)) >> 32) - ((t castto(int64)) >> 32)) castto(uint64); + ;; + t = (u.dig[j + n] castto(uint64)) - carry + u.dig[j + n] = t castto(uint32) + q.dig[j] = qhat castto(uint32) + /* adjust */ + if t castto(int64) < 0 + q.dig[j]-- + carry = 0 + for i = 0; i < n; i++ + t = (u.dig[i+j] castto(uint64)) + (v.dig[i] castto(uint64)) + carry + u.dig[i+j] = t castto(uint32) + carry = t >> 32 + ;; + u.dig[j+n] = u.dig[j+n] + (carry castto(uint32)); + ;; + + ;; + /* undo the biasing for remainder */ + u = bigshri(u, shift) + -> (trim(q), trim(u)) +} + +/* computes b^e % m */ +const bigmodpow = {base, exp, mod + var r, n + + r = mkbigint(1) + n = 0 + while !bigiszero(exp) + if (exp.dig[0] & 1) != 0 + bigmul(r, base) + bigmod(r, mod) + ;; + bigshri(exp, 1) + bigmul(base, base) + bigmod(base, mod) + ;; + -> bigmove(base, r) +} + +/* returns the number of leading zeros */ +const nlz = {a : uint32 + var n + + if a == 0 + -> 32 + ;; + n = 0 + if a <= 0x0000ffff + n += 16 + a <<= 16 + ;; + if a <= 0x00ffffff + n += 8 + a <<= 8 + ;; + if a <= 0x0fffffff + n += 4 + a <<= 4 + ;; + if a <= 0x3fffffff + n += 2 + a <<= 2 + ;; + if a <= 0x7fffffff + n += 1 + a <<= 1 + ;; + -> n +} + + +/* a <<= b */ +const bigshl = {a, b + match b.dig.len + | 0: -> a + | 1: -> bigshli(a, b.dig[0] castto(uint64)) + | n: die("shift by way too much\n") + ;; +} + +/* a >>= b, unsigned */ +const bigshr = {a, b + match b.dig.len + | 0: -> a + | 1: -> bigshri(a, b.dig[0] castto(uint64)) + | n: die("shift by way too much\n") + ;; +} + +/* a + b, b is integer. +FIXME: acually make this a performace improvement +*/ +generic bigaddi = {a, b + var bigb : bigint + var dig : uint32[2] + + bigdigit(&bigb, b < 0, b castto(uint64), dig[:]) + bigadd(a, &bigb) + -> a +} + +generic bigsubi = {a, b : @a::(numeric,integral) + var bigb : bigint + var dig : uint32[2] + + bigdigit(&bigb, b < 0, b castto(uint64), dig[:]) + bigsub(a, &bigb) + -> a +} + +generic bigmuli = {a, b + var bigb : bigint + var dig : uint32[2] + + bigdigit(&bigb, b < 0, b castto(uint64), dig[:]) + bigmul(a, &bigb) + -> a +} + +generic bigdivi = {a, b + var bigb : bigint + var dig : uint32[2] + + bigdigit(&bigb, b < 0, b castto(uint64), dig[:]) + bigdiv(a, &bigb) + -> a +} + +/* + a << s, with integer arg. + logical left shift. any other type would be illogical. + */ +generic bigshli = {a, s : @a::(numeric,integral) + var off, shift + var t, carry + var i + + assert(s >= 0, "shift amount must be positive") + off = (s castto(uint64)) / 32 + shift = (s castto(uint64)) % 32 + + /* zero shifted by anything is zero */ + if a.sign == 0 + -> a + ;; + a.dig = slzgrow(a.dig, 1 + a.dig.len + off castto(size)) + /* blit over the base values */ + for i = a.dig.len; i > off; i-- + a.dig[i - 1] = a.dig[i - 1 - off] + ;; + for i = 0; i < off; i++ + a.dig[i] = 0 + ;; + /* and shift over by the remainder */ + carry = 0 + for i = 0; i < a.dig.len; i++ + t = (a.dig[i] castto(uint64)) << shift + a.dig[i] = (t | carry) castto(uint32) + carry = t >> 32 + ;; + -> trim(a) +} + +/* logical shift right, zero fills. sign remains untouched. */ +generic bigshri = {a, s + var off, shift + var t, carry + var i + + assert(s >= 0, "shift amount must be positive") + off = (s castto(uint64)) / 32 + shift = (s castto(uint64)) % 32 + + /* blit over the base values */ + for i = 0; i < a.dig.len - off; i++ + a.dig[i] = a.dig[i + off] + ;; + for i = a.dig.len - off; i < a.dig.len; i++ + a.dig[i] = 0 + ;; + /* and shift over by the remainder */ + carry = 0 + for i = a.dig.len; i > 0; i-- + t = (a.dig[i - 1] castto(uint64)) + a.dig[i - 1] = (carry | (t >> shift)) castto(uint32) + carry = t << (32 - shift) + ;; + -> trim(a) +} + +/* creates a bigint on the stack; should not be modified. */ +const bigdigit = {v, isneg : bool, val : uint64, dig + v.sign = 1 + if isneg + val = -val + v.sign = -1 + ;; + if val == 0 + v.sign = 0 + v.dig = [][:] + elif val < Base + v.dig = dig[:1] + v.dig[0] = val castto(uint32) + else + v.dig = dig + v.dig[0] = val castto(uint32) + v.dig[1] = (val >> 32) castto(uint32) + ;; +} + +/* trims leading zeros */ +const trim = {a + var i + + for i = a.dig.len; i > 0; i-- + if a.dig[i - 1] != 0 + break + ;; + ;; + a.dig = slgrow(a.dig, i) + if i == 0 + a.sign = 0 + elif a.sign == 0 + a.sign = 1 + ;; + -> a +} + diff --git a/lib/std/bitset.myr b/lib/std/bitset.myr new file mode 100644 index 0000000..7843c7d --- /dev/null +++ b/lib/std/bitset.myr @@ -0,0 +1,155 @@ +use "alloc.use" +use "die.use" +use "extremum.use" +use "mk.use" +use "slcp.use" +use "sldup.use" +use "slfill.use" +use "types.use" + +pkg std = + type bitset = struct + bits : size[:] + ;; + + const mkbs : (-> bitset#) + const bsdup : (bs : bitset# -> bitset#) + const bsfree : (bs : bitset# -> void) + + const bsmax : (a : bitset# -> size) + + generic bsput : (bs : bitset#, v : @a::(integral,numeric) -> void) + generic bsdel : (bs : bitset#, v : @a::(integral,numeric) -> void) + generic bshas : (bs : bitset#, v : @a::(integral,numeric) -> bool) + + const bsdiff : (a : bitset#, b : bitset# -> void) + const bsintersect : (a : bitset#, b : bitset# -> void) + const bsunion : (a : bitset#, b : bitset# -> void) + const bseq : (a : bitset#, b : bitset# -> bool) + const bsissubset : (a : bitset#, b : bitset# -> bool) + + + const bsclear : (bs : bitset# -> bitset#) +;; + +const mkbs = { + -> zalloc() +} + +const bsdup = {bs + -> mk([.bits=sldup(bs.bits)]) +} + +const bsfree = {bs + slfree(bs.bits) + free(bs) +} + +const bsclear = {bs + slfill(bs.bits, 0) + -> bs +} + +const bsmax = {bs + -> bs.bits.len * sizeof(size) * 8 +} + +generic bsput = {bs, v + var idx + var off + + idx = (v castto(size)) / (8*sizeof(size)) + off = (v castto(size)) % (8*sizeof(size)) + ensurelen(bs, idx) + bs.bits[idx] |= (1 << off) +} + +generic bsdel = {bs, v + var idx + var off + + idx = (v castto(size)) / (8*sizeof(size)) + off = (v castto(size)) % (8*sizeof(size)) + if idx >= bs.bits.len + -> + ;; + bs.bits[idx] &= ~(1 << off) +} + +generic bshas = {bs, v + var idx + var off + + idx = (v castto(size)) / (8*sizeof(size)) + off = (v castto(size)) % (8*sizeof(size)) + if idx >= bs.bits.len + -> false + ;; + -> (bs.bits[idx] & (1 << off)) != 0 +} + +const bsunion = {a, b + var i + + eqsz(a, b) + for i = 0; i < b.bits.len; i++ + a.bits[i] |= b.bits[i] + ;; +} + +const bsintersect = {a, b + var i, n + + n = min(a.bits.len, b.bits.len) + for i = 0; i < n; i++ + a.bits[i] &= b.bits[i] + ;; +} + +const bsdiff = {a, b + var i, n + + n = min(b.bits.len, a.bits.len) + for i = 0; i < n; i++ + a.bits[i] &= ~b.bits[i] + ;; +} + +const bsissubset = {a, b + var i + + eqsz(a, b); + for i = 0; i < a.bits.len; i++ + if (b.bits[i] & a.bits[i]) != b.bits[i] + -> false + ;; + ;; + -> true +} + +const bseq = {a, b + var i + + eqsz(a, b) + for i = 0; i < a.bits.len; i++ + if a.bits[i] != b.bits[i] + -> false + ;; + ;; + -> true +} + +const ensurelen = {bs, len + if bs.bits.len <= len + bs.bits = slzgrow(bs.bits, len + 1) + ;; +} + +const eqsz = {a, b + var sz + + sz = max(a.bits.len, b.bits.len) + ensurelen(a, sz) + ensurelen(b, sz) +} + diff --git a/lib/std/blat.myr b/lib/std/blat.myr new file mode 100644 index 0000000..90c0f94 --- /dev/null +++ b/lib/std/blat.myr @@ -0,0 +1,32 @@ +use "syswrap.use" + +pkg std = + const blat : (path : byte[:], buf : byte[:], perm : int64 -> bool) + const fblat : (f : fd, buf : byte[:] -> bool) +;; + +const blat = {path, buf, perm + var fd + + fd = openmode(path, Ocreat|Owronly, perm) + if fd < 0 + -> false + ;; + -> fblat(fd, buf) +} + + +const fblat = {fd, buf + var written, n + + n = 0 + while true + written = write(fd, buf[n:]) + if written <= 0 + goto done + ;; + n += written + ;; +:done + -> written == 0 && n == buf.len +} diff --git a/lib/std/bld.sub b/lib/std/bld.sub new file mode 100644 index 0000000..b84be64 --- /dev/null +++ b/lib/std/bld.sub @@ -0,0 +1,103 @@ +lib sys = + sys+freebsd-x64.myr + sys+linux-x64.myr + sys+osx-x64.myr + sys+plan9-x64.myr + syscall+freebsd-x64.s + syscall+linux-x64.s + syscall+osx-x64.s + syscall+plan9-x64.s + syserrno+linux.myr + syserrno+osx.myr + systypes.myr + ifreq+freebsd.myr + ifreq+linux.myr + ifreq+osx.myr + ifreq+plan9.myr + ifreq.myr # dummy file: plan9 doesn't have ifreq + util+plan9-x64.s + util+posixy-x64.s +;; + +lib std {inc=.} = + lib sys + + # portable files + alloc.myr + bigint.myr + bitset.myr + blat.myr + chartype.myr + clear.myr + cmp.myr + cstrconv.myr + die.myr + dirname.myr + endian.myr + errno.myr + execvp.myr + extremum.myr + fltbits.myr + fltfmt.myr + fmt.myr + fmtfuncs.myr + getcwd.myr + getint.myr + hashfuncs.myr + hasprefix.myr + hassuffix.myr + htab.myr + intparse.myr + introspect.myr + ipparse.myr + mk.myr + mkpath.myr + now.myr + option.myr + optparse.myr + pathjoin.myr + putint.myr + rand.myr + result.myr + search.myr + slcp.myr + sldup.myr + sleq.myr + slfill.myr + sljoin.myr + slpush.myr + slput.myr + slurp.myr + sort.myr + spork.myr + strbuf.myr + strfind.myr + strjoin.myr + strsplit.myr + strstrip.myr + swap.myr + try.myr + types.myr + units.myr + utf.myr + varargs.myr + + # platform specific files + env+plan9.myr + env+posixy.myr + errno+plan9.myr + dir+freebsd.myr + dir+linux.myr + dir+osx.myr + wait+posixy.myr + wait+plan9.myr + dial+posixy.myr + dial+plan9.myr + resolve+posixy.myr + resolve+plan9.myr + syswrap-ss+linux.myr + syswrap-ss+osx.myr + syswrap-ss+plan9.myr + syswrap+plan9.myr + syswrap+posixy.myr +;; diff --git a/lib/std/build.sh b/lib/std/build.sh new file mode 100755 index 0000000..3c1aa99 --- /dev/null +++ b/lib/std/build.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ -z "`which mbld`" ]; then + ../myrbuild/myrbuild -I. -C$MYR_MC -M$MYR_MUSE $@ +else + mbld +fi + diff --git a/lib/std/chartype.myr b/lib/std/chartype.myr new file mode 100644 index 0000000..fe59202 --- /dev/null +++ b/lib/std/chartype.myr @@ -0,0 +1,1242 @@ +use "die.use" +use "types.use" + +/* + Tables adapted from plan 9's runetype.c, + which lives in sys/src/libc/port/runetype.c +*/ + +pkg std = + /* predicates */ + const isalpha : (c : char -> bool) + const isdigit : (c : char -> bool) + const isxdigit : (c : char -> bool) + const isnum : (c : char -> bool) + const isalnum : (c : char -> bool) + const isspace : (c : char -> bool) + const isblank : (c : char -> bool) + const islower : (c : char -> bool) + const isupper : (c : char -> bool) + const istitle : (c : char -> bool) + + /* transforms */ + const tolower : (c : char -> char) + const toupper : (c : char -> char) + const totitle : (c : char -> char) + + generic charval : (c : char, base : int -> @a::(integral,numeric)) +;; + +extern const put : (fmt : byte[:], args : ... -> size) + +/* + * alpha ranges - + * only covers ranges not in lower||upper + */ +const ralpha2 = [ + 0x00d8, 0x00f6, /* Ø - ö */ + 0x00f8, 0x01f5, /* ø - ǵ */ + 0x0250, 0x02a8, /* É - ʨ */ + 0x038e, 0x03a1, /* ÎŽ - Ρ */ + 0x03a3, 0x03ce, /* Σ - ÏŽ */ + 0x03d0, 0x03d6, /* Ï - Ï– */ + 0x03e2, 0x03f3, /* Ï¢ - ϳ */ + 0x0490, 0x04c4, /* Ò - Ó„ */ + 0x0561, 0x0587, /* Õ¡ - Ö‡ */ + 0x05d0, 0x05ea, /* × - ת */ + 0x05f0, 0x05f2, /* ×° - ײ */ + 0x0621, 0x063a, /* Ø¡ - غ */ + 0x0640, 0x064a, /* Ù€ - ÙŠ */ + 0x0671, 0x06b7, /* Ù± - Ú· */ + 0x06ba, 0x06be, /* Úº - Ú¾ */ + 0x06c0, 0x06ce, /* Û€ - ÛŽ */ + 0x06d0, 0x06d3, /* Û - Û“ */ + 0x0905, 0x0939, /* अ - ह */ + 0x0958, 0x0961, /* क़ - ॡ */ + 0x0985, 0x098c, /* অ - ঌ */ + 0x098f, 0x0990, /* ঠ- ঠ*/ + 0x0993, 0x09a8, /* ও - ন */ + 0x09aa, 0x09b0, /* প - র */ + 0x09b6, 0x09b9, /* শ - হ */ + 0x09dc, 0x09dd, /* à§œ - à§ */ + 0x09df, 0x09e1, /* à§Ÿ - à§¡ */ + 0x09f0, 0x09f1, /* à§° - à§± */ + 0x0a05, 0x0a0a, /* ਅ - ਊ */ + 0x0a0f, 0x0a10, /* ਠ- ਠ*/ + 0x0a13, 0x0a28, /* ਓ - ਨ */ + 0x0a2a, 0x0a30, /* ਪ - ਰ */ + 0x0a32, 0x0a33, /* ਲ - ਲ਼ */ + 0x0a35, 0x0a36, /* ਵ - ਸ਼ */ + 0x0a38, 0x0a39, /* ਸ - ਹ */ + 0x0a59, 0x0a5c, /* à©™ - ੜ */ + 0x0a85, 0x0a8b, /* અ - ઋ */ + 0x0a8f, 0x0a91, /* ઠ- ઑ */ + 0x0a93, 0x0aa8, /* ઓ - ન */ + 0x0aaa, 0x0ab0, /* પ - ર */ + 0x0ab2, 0x0ab3, /* લ - ળ */ + 0x0ab5, 0x0ab9, /* વ - હ */ + 0x0b05, 0x0b0c, /* ଅ - ଌ */ + 0x0b0f, 0x0b10, /* ଠ- ଠ*/ + 0x0b13, 0x0b28, /* ଓ - ନ */ + 0x0b2a, 0x0b30, /* ପ - ର */ + 0x0b32, 0x0b33, /* ଲ - ଳ */ + 0x0b36, 0x0b39, /* ଶ - ହ */ + 0x0b5c, 0x0b5d, /* àœ - à */ + 0x0b5f, 0x0b61, /* àŸ - à¡ */ + 0x0b85, 0x0b8a, /* à®… - ஊ */ + 0x0b8e, 0x0b90, /* எ - à® */ + 0x0b92, 0x0b95, /* à®’ - க */ + 0x0b99, 0x0b9a, /* à®™ - ச */ + 0x0b9e, 0x0b9f, /* ஞ - ட */ + 0x0ba3, 0x0ba4, /* ண - த */ + 0x0ba8, 0x0baa, /* ந - ப */ + 0x0bae, 0x0bb5, /* à®® - வ */ + 0x0bb7, 0x0bb9, /* à®· - ஹ */ + 0x0c05, 0x0c0c, /* à°… - à°Œ */ + 0x0c0e, 0x0c10, /* à°Ž - à° */ + 0x0c12, 0x0c28, /* à°’ - à°¨ */ + 0x0c2a, 0x0c33, /* à°ª - à°³ */ + 0x0c35, 0x0c39, /* à°µ - à°¹ */ + 0x0c60, 0x0c61, /* à± - ౡ */ + 0x0c85, 0x0c8c, /* ಅ - ಌ */ + 0x0c8e, 0x0c90, /* ಎ - ಠ*/ + 0x0c92, 0x0ca8, /* ಒ - ನ */ + 0x0caa, 0x0cb3, /* ಪ - ಳ */ + 0x0cb5, 0x0cb9, /* ವ - ಹ */ + 0x0ce0, 0x0ce1, /* à³ - ೡ */ + 0x0d05, 0x0d0c, /* à´… - à´Œ */ + 0x0d0e, 0x0d10, /* à´Ž - à´ */ + 0x0d12, 0x0d28, /* à´’ - à´¨ */ + 0x0d2a, 0x0d39, /* à´ª - à´¹ */ + 0x0d60, 0x0d61, /* ൠ- ൡ */ + 0x0e01, 0x0e30, /* ภ- ะ */ + 0x0e32, 0x0e33, /* า - ำ */ + 0x0e40, 0x0e46, /* เ - ๆ */ + 0x0e5a, 0x0e5b, /* ๚ - ๛ */ + 0x0e81, 0x0e82, /* ຠ- ຂ */ + 0x0e87, 0x0e88, /* ງ - ຈ */ + 0x0e94, 0x0e97, /* ດ - ທ */ + 0x0e99, 0x0e9f, /* ນ - ຟ */ + 0x0ea1, 0x0ea3, /* ມ - ຣ */ + 0x0eaa, 0x0eab, /* ສ - ຫ */ + 0x0ead, 0x0eae, /* ຠ- ຮ */ + 0x0eb2, 0x0eb3, /* າ - ຳ */ + 0x0ec0, 0x0ec4, /* ເ - ໄ */ + 0x0edc, 0x0edd, /* ໜ - à» */ + 0x0f18, 0x0f19, /* ༘ - ༙ */ + 0x0f40, 0x0f47, /* ཀ - ཇ */ + 0x0f49, 0x0f69, /* ཉ - ཀྵ */ + 0x10d0, 0x10f6, /* რ- ჶ */ + 0x1100, 0x1159, /* á„€ - á…™ */ + 0x115f, 0x11a2, /* á…Ÿ - ᆢ */ + 0x11a8, 0x11f9, /* ᆨ - ᇹ */ + 0x1e00, 0x1e9b, /* Ḁ - ẛ */ + 0x1f50, 0x1f57, /* á½ - á½— */ + 0x1f80, 0x1fb4, /* á¾€ - á¾´ */ + 0x1fb6, 0x1fbc, /* á¾¶ - á¾¼ */ + 0x1fc2, 0x1fc4, /* á¿‚ - á¿„ */ + 0x1fc6, 0x1fcc, /* ῆ - ῌ */ + 0x1fd0, 0x1fd3, /* á¿ - á¿“ */ + 0x1fd6, 0x1fdb, /* á¿– - á¿› */ + 0x1fe0, 0x1fec, /* á¿ - Ῥ */ + 0x1ff2, 0x1ff4, /* ῲ - á¿´ */ + 0x1ff6, 0x1ffc, /* á¿¶ - ῼ */ + 0x210a, 0x2113, /* ℊ - â„“ */ + 0x2115, 0x211d, /* â„• - â„ */ + 0x2120, 0x2122, /* â„ - â„¢ */ + 0x212a, 0x2131, /* K - ℱ */ + 0x2133, 0x2138, /* ℳ - ℸ */ + 0x3041, 0x3094, /* ã - ã‚” */ + 0x30a1, 0x30fa, /* ã‚¡ - ヺ */ + 0x3105, 0x312c, /* ã„… - ㄬ */ + 0x3131, 0x318e, /* ㄱ - ㆎ */ + 0x3192, 0x319f, /* ㆒ - ㆟ */ + 0x3260, 0x327b, /* ㉠- ㉻ */ + 0x328a, 0x32b0, /* ㊊ - ㊰ */ + 0x32d0, 0x32fe, /* ã‹ - ㋾ */ + 0x3300, 0x3357, /* ㌀ - ã— */ + 0x3371, 0x3376, /* ã± - ã¶ */ + 0x337b, 0x3394, /* ã» - ㎔ */ + 0x3399, 0x339e, /* ㎙ - ㎞ */ + 0x33a9, 0x33ad, /* ㎩ - ㎠*/ + 0x33b0, 0x33c1, /* ㎰ - ã */ + 0x33c3, 0x33c5, /* ム- ã… */ + 0x33c7, 0x33d7, /* ㇠- ã— */ + 0x33d9, 0x33dd, /* ã™ - ã */ + 0x4e00, 0x9fff, /* 一 - é¿¿ */ + 0xac00, 0xd7a3, /* ê°€ - 힣 */ + 0xf900, 0xfb06, /* 豈 - st */ + 0xfb13, 0xfb17, /* ﬓ - ﬗ */ + 0xfb1f, 0xfb28, /* ײַ - ﬨ */ + 0xfb2a, 0xfb36, /* שׁ - זּ */ + 0xfb38, 0xfb3c, /* טּ - לּ */ + 0xfb40, 0xfb41, /* ï€ - ï */ + 0xfb43, 0xfb44, /* ïƒ - ï„ */ + 0xfb46, 0xfbb1, /* ï† - ï®± */ + 0xfbd3, 0xfd3d, /* ﯓ - ï´½ */ + 0xfd50, 0xfd8f, /* ïµ - ï¶ */ + 0xfd92, 0xfdc7, /* ï¶’ - ï·‡ */ + 0xfdf0, 0xfdf9, /* ï·° - ï·¹ */ + 0xfe70, 0xfe72, /* ï¹° - ï¹² */ + 0xfe76, 0xfefc, /* ï¹¶ - ﻼ */ + 0xff66, 0xff6f, /* ヲ - ッ */ + 0xff71, 0xff9d, /* ï½± - ï¾ */ + 0xffa0, 0xffbe, /* ï¾ - ï¾¾ */ + 0xffc2, 0xffc7, /* ï¿‚ - ᅦ */ + 0xffca, 0xffcf, /* ᅧ - ï¿ */ + 0xffd2, 0xffd7, /* ï¿’ - ï¿— */ + 0xffda, 0xffdc /* ᅳ - ᅵ */ +] + +/* + * alpha singlets - + * only covers ranges not in lower||upper + */ +const ralpha1 = [ + 0x00aa, /* ª */ + 0x00b5, /* µ */ + 0x00ba, /* º */ + 0x03da, /* Ïš */ + 0x03dc, /* Ïœ */ + 0x03de, /* Ïž */ + 0x03e0, /* Ï */ + 0x06d5, /* Û• */ + 0x09b2, /* ল */ + 0x0a5e, /* ਫ਼ */ + 0x0a8d, /* ઠ*/ + 0x0ae0, /* à« */ + 0x0b9c, /* ஜ */ + 0x0cde, /* ೞ */ + 0x0e4f, /* ๠*/ + 0x0e84, /* ຄ */ + 0x0e8a, /* ຊ */ + 0x0e8d, /* ຠ*/ + 0x0ea5, /* ລ */ + 0x0ea7, /* ວ */ + 0x0eb0, /* ະ */ + 0x0ebd, /* ຽ */ + 0x1fbe, /* á¾¾ */ + 0x207f, /* â¿ */ + 0x20a8, /* ₨ */ + 0x2102, /* â„‚ */ + 0x2107, /* ℇ */ + 0x2124, /* ℤ */ + 0x2126, /* Ω */ + 0x2128, /* ℨ */ + 0xfb3e, /* מּ */ + 0xfe74 /* ï¹´ */ +] + +/* + * space ranges + */ +const rspace2 = [ + 0x0009, 0x0009, /* tab */ + 0x0020, 0x0020, /* space */ + 0x0085, 0x0085, + 0x00a0, 0x00a0, /* */ + 0x1680, 0x1680, + 0x180e, 0x180e, + 0x2000, 0x200b, /*   - ​ */ + 0x2028, 0x2029, /* 
 - 
 */ + 0x202f, 0x202f, + 0x205f, 0x205f, + 0x3000, 0x3000, /*   */ + 0xfeff, 0xfeff /*  */ +] + +/* + * lower case ranges + * 3rd col is conversion excess 500 + */ +const rtoupper2 = [ + 0x0061, 0x007a, 468, /* a-z A-Z */ + 0x00e0, 0x00f6, 468, /* à -ö À-Ö */ + 0x00f8, 0x00fe, 468, /* ø-þ Ø-Þ */ + 0x0256, 0x0257, 295, /* É–-É— Ɖ-ÆŠ */ + 0x0258, 0x0259, 298, /* ɘ-É™ ÆŽ-Æ */ + 0x028a, 0x028b, 283, /* ÊŠ-Ê‹ Ʊ-Ʋ */ + 0x03ad, 0x03af, 463, /* Î-ί Έ-Ί */ + 0x03b1, 0x03c1, 468, /* α-Ï Î‘-Ρ */ + 0x03c3, 0x03cb, 468, /* σ-Ï‹ Σ-Ϋ */ + 0x03cd, 0x03ce, 437, /* Ï-ÏŽ ÎŽ-Î */ + 0x0430, 0x044f, 468, /* а-Ñ Ð-Я */ + 0x0451, 0x045c, 420, /* Ñ‘-Ñœ Ð-ÐŒ */ + 0x045e, 0x045f, 420, /* Ñž-ÑŸ ÐŽ-Ð */ + 0x0561, 0x0586, 452, /* Õ¡-Ö† Ô±-Õ– */ + 0x1f00, 0x1f07, 508, /* á¼€-ἇ Ἀ-á¼ */ + 0x1f10, 0x1f15, 508, /* á¼-ἕ Ἐ-á¼ */ + 0x1f20, 0x1f27, 508, /* á¼ -á¼§ Ἠ-Ἧ */ + 0x1f30, 0x1f37, 508, /* á¼°-á¼· Ἰ-Ἷ */ + 0x1f40, 0x1f45, 508, /* á½€-á½… Ὀ-á½ */ + 0x1f60, 0x1f67, 508, /* á½ -á½§ Ὠ-Ὧ */ + 0x1f70, 0x1f71, 574, /* á½°-á½± Ὰ-á¾» */ + 0x1f72, 0x1f75, 586, /* á½²-á½µ Ὲ-á¿‹ */ + 0x1f76, 0x1f77, 600, /* á½¶-á½· Ὶ-á¿› */ + 0x1f78, 0x1f79, 628, /* ὸ-á½¹ Ὸ-Ό */ + 0x1f7a, 0x1f7b, 612, /* ὺ-á½» Ὺ-á¿« */ + 0x1f7c, 0x1f7d, 626, /* á½¼-á½½ Ὼ-á¿» */ + 0x1f80, 0x1f87, 508, /* á¾€-ᾇ ᾈ-á¾ */ + 0x1f90, 0x1f97, 508, /* á¾-á¾— ᾘ-ᾟ */ + 0x1fa0, 0x1fa7, 508, /* á¾ -á¾§ ᾨ-ᾯ */ + 0x1fb0, 0x1fb1, 508, /* á¾°-á¾± Ᾰ-á¾¹ */ + 0x1fd0, 0x1fd1, 508, /* á¿-á¿‘ Ῐ-á¿™ */ + 0x1fe0, 0x1fe1, 508, /* á¿ -á¿¡ Ῠ-á¿© */ + 0x2170, 0x217f, 484, /* â…°-â…¿ â… -â…¯ */ + 0x24d0, 0x24e9, 474, /* â“-â“© â’¶-â“ */ + 0xff41, 0xff5a, 468 /* ï½-z A-Z */ +] + +/* + * lower case singlets + * 2nd col is conversion excess 500 + */ +const rtoupper1 = [ + 0x00ff, 621, /* ÿ Ÿ */ + 0x0101, 499, /* Ä Ä€ */ + 0x0103, 499, /* ă Ä‚ */ + 0x0105, 499, /* Ä… Ä„ */ + 0x0107, 499, /* ć Ć */ + 0x0109, 499, /* ĉ Ĉ */ + 0x010b, 499, /* Ä‹ ÄŠ */ + 0x010d, 499, /* Ä ÄŒ */ + 0x010f, 499, /* Ä ÄŽ */ + 0x0111, 499, /* Ä‘ Ä */ + 0x0113, 499, /* Ä“ Ä’ */ + 0x0115, 499, /* Ä• Ä” */ + 0x0117, 499, /* Ä— Ä– */ + 0x0119, 499, /* Ä™ Ę */ + 0x011b, 499, /* Ä› Äš */ + 0x011d, 499, /* Ä Äœ */ + 0x011f, 499, /* ÄŸ Äž */ + 0x0121, 499, /* Ä¡ Ä */ + 0x0123, 499, /* Ä£ Ä¢ */ + 0x0125, 499, /* Ä¥ Ĥ */ + 0x0127, 499, /* ħ Ħ */ + 0x0129, 499, /* Ä© Ĩ */ + 0x012b, 499, /* Ä« Ī */ + 0x012d, 499, /* Ä Ä¬ */ + 0x012f, 499, /* į Ä® */ + 0x0131, 268, /* ı I */ + 0x0133, 499, /* ij IJ */ + 0x0135, 499, /* ĵ Ä´ */ + 0x0137, 499, /* Ä· Ķ */ + 0x013a, 499, /* ĺ Ĺ */ + 0x013c, 499, /* ļ Ä» */ + 0x013e, 499, /* ľ Ľ */ + 0x0140, 499, /* Å€ Ä¿ */ + 0x0142, 499, /* Å‚ Å */ + 0x0144, 499, /* Å„ Ń */ + 0x0146, 499, /* ņ Å… */ + 0x0148, 499, /* ň Ň */ + 0x014b, 499, /* Å‹ ÅŠ */ + 0x014d, 499, /* Å ÅŒ */ + 0x014f, 499, /* Å ÅŽ */ + 0x0151, 499, /* Å‘ Å */ + 0x0153, 499, /* Å“ Å’ */ + 0x0155, 499, /* Å• Å” */ + 0x0157, 499, /* Å— Å– */ + 0x0159, 499, /* Å™ Ř */ + 0x015b, 499, /* Å› Åš */ + 0x015d, 499, /* Å Åœ */ + 0x015f, 499, /* ÅŸ Åž */ + 0x0161, 499, /* Å¡ Å */ + 0x0163, 499, /* Å£ Å¢ */ + 0x0165, 499, /* Å¥ Ť */ + 0x0167, 499, /* ŧ Ŧ */ + 0x0169, 499, /* Å© Ũ */ + 0x016b, 499, /* Å« Ū */ + 0x016d, 499, /* ŠŬ */ + 0x016f, 499, /* ů Å® */ + 0x0171, 499, /* ű Ű */ + 0x0173, 499, /* ų Ų */ + 0x0175, 499, /* ŵ Å´ */ + 0x0177, 499, /* Å· Ŷ */ + 0x017a, 499, /* ź Ź */ + 0x017c, 499, /* ż Å» */ + 0x017e, 499, /* ž Ž */ + 0x017f, 200, /* Å¿ S */ + 0x0183, 499, /* ƃ Æ‚ */ + 0x0185, 499, /* Æ… Æ„ */ + 0x0188, 499, /* ƈ Ƈ */ + 0x018c, 499, /* ÆŒ Æ‹ */ + 0x0192, 499, /* Æ’ Æ‘ */ + 0x0199, 499, /* Æ™ Ƙ */ + 0x01a1, 499, /* Æ¡ Æ */ + 0x01a3, 499, /* Æ£ Æ¢ */ + 0x01a5, 499, /* Æ¥ Ƥ */ + 0x01a8, 499, /* ƨ Ƨ */ + 0x01ad, 499, /* Æ Æ¬ */ + 0x01b0, 499, /* ư Ư */ + 0x01b4, 499, /* Æ´ Ƴ */ + 0x01b6, 499, /* ƶ Ƶ */ + 0x01b9, 499, /* ƹ Ƹ */ + 0x01bd, 499, /* ƽ Ƽ */ + 0x01c5, 499, /* Ç… Ç„ */ + 0x01c6, 498, /* dž Ç„ */ + 0x01c8, 499, /* Lj LJ */ + 0x01c9, 498, /* lj LJ */ + 0x01cb, 499, /* Ç‹ ÇŠ */ + 0x01cc, 498, /* ÇŒ ÇŠ */ + 0x01ce, 499, /* ÇŽ Ç */ + 0x01d0, 499, /* Ç Ç */ + 0x01d2, 499, /* Ç’ Ç‘ */ + 0x01d4, 499, /* Ç” Ç“ */ + 0x01d6, 499, /* Ç– Ç• */ + 0x01d8, 499, /* ǘ Ç— */ + 0x01da, 499, /* Çš Ç™ */ + 0x01dc, 499, /* Çœ Ç› */ + 0x01df, 499, /* ÇŸ Çž */ + 0x01e1, 499, /* Ç¡ Ç */ + 0x01e3, 499, /* Ç£ Ç¢ */ + 0x01e5, 499, /* Ç¥ Ǥ */ + 0x01e7, 499, /* ǧ Ǧ */ + 0x01e9, 499, /* Ç© Ǩ */ + 0x01eb, 499, /* Ç« Ǫ */ + 0x01ed, 499, /* Ç Ç¬ */ + 0x01ef, 499, /* ǯ Ç® */ + 0x01f2, 499, /* Dz DZ */ + 0x01f3, 498, /* dz DZ */ + 0x01f5, 499, /* ǵ Ç´ */ + 0x01fb, 499, /* Ç» Ǻ */ + 0x01fd, 499, /* ǽ Ǽ */ + 0x01ff, 499, /* Ç¿ Ǿ */ + 0x0201, 499, /* È È€ */ + 0x0203, 499, /* ȃ È‚ */ + 0x0205, 499, /* È… È„ */ + 0x0207, 499, /* ȇ Ȇ */ + 0x0209, 499, /* ȉ Ȉ */ + 0x020b, 499, /* È‹ ÈŠ */ + 0x020d, 499, /* È ÈŒ */ + 0x020f, 499, /* È ÈŽ */ + 0x0211, 499, /* È‘ È */ + 0x0213, 499, /* È“ È’ */ + 0x0215, 499, /* È• È” */ + 0x0217, 499, /* È— È– */ + 0x0253, 290, /* É“ Æ */ + 0x0254, 294, /* É” Ɔ */ + 0x025b, 297, /* É› Æ */ + 0x0260, 295, /* É Æ“ */ + 0x0263, 293, /* É£ Æ” */ + 0x0268, 291, /* ɨ Æ— */ + 0x0269, 289, /* É© Æ– */ + 0x026f, 289, /* ɯ Æœ */ + 0x0272, 287, /* ɲ Æ */ + 0x0283, 282, /* ʃ Æ© */ + 0x0288, 282, /* ʈ Æ® */ + 0x0292, 281, /* Ê’ Æ· */ + 0x03ac, 462, /* ά Ά */ + 0x03cc, 436, /* ÏŒ ÎŒ */ + 0x03d0, 438, /* Ï Î’ */ + 0x03d1, 443, /* Ï‘ Θ */ + 0x03d5, 453, /* Ï• Φ */ + 0x03d6, 446, /* Ï– Î */ + 0x03e3, 499, /* Ï£ Ï¢ */ + 0x03e5, 499, /* Ï¥ Ϥ */ + 0x03e7, 499, /* ϧ Ϧ */ + 0x03e9, 499, /* Ï© Ϩ */ + 0x03eb, 499, /* Ï« Ϫ */ + 0x03ed, 499, /* Ï Ï¬ */ + 0x03ef, 499, /* ϯ Ï® */ + 0x03f0, 414, /* ϰ Κ */ + 0x03f1, 420, /* ϱ Ρ */ + 0x0461, 499, /* Ñ¡ Ñ */ + 0x0463, 499, /* Ñ£ Ñ¢ */ + 0x0465, 499, /* Ñ¥ Ѥ */ + 0x0467, 499, /* ѧ Ѧ */ + 0x0469, 499, /* Ñ© Ѩ */ + 0x046b, 499, /* Ñ« Ѫ */ + 0x046d, 499, /* Ñ Ñ¬ */ + 0x046f, 499, /* ѯ Ñ® */ + 0x0471, 499, /* ѱ Ѱ */ + 0x0473, 499, /* ѳ Ѳ */ + 0x0475, 499, /* ѵ Ñ´ */ + 0x0477, 499, /* Ñ· Ѷ */ + 0x0479, 499, /* ѹ Ѹ */ + 0x047b, 499, /* Ñ» Ѻ */ + 0x047d, 499, /* ѽ Ѽ */ + 0x047f, 499, /* Ñ¿ Ѿ */ + 0x0481, 499, /* Ò Ò€ */ + 0x0491, 499, /* Ò‘ Ò */ + 0x0493, 499, /* Ò“ Ò’ */ + 0x0495, 499, /* Ò• Ò” */ + 0x0497, 499, /* Ò— Ò– */ + 0x0499, 499, /* Ò™ Ò˜ */ + 0x049b, 499, /* Ò› Òš */ + 0x049d, 499, /* Ò Òœ */ + 0x049f, 499, /* ÒŸ Òž */ + 0x04a1, 499, /* Ò¡ Ò */ + 0x04a3, 499, /* Ò£ Ò¢ */ + 0x04a5, 499, /* Ò¥ Ò¤ */ + 0x04a7, 499, /* Ò§ Ò¦ */ + 0x04a9, 499, /* Ò© Ò¨ */ + 0x04ab, 499, /* Ò« Òª */ + 0x04ad, 499, /* Ò Ò¬ */ + 0x04af, 499, /* Ò¯ Ò® */ + 0x04b1, 499, /* Ò± Ò° */ + 0x04b3, 499, /* Ò³ Ò² */ + 0x04b5, 499, /* Òµ Ò´ */ + 0x04b7, 499, /* Ò· Ò¶ */ + 0x04b9, 499, /* Ò¹ Ò¸ */ + 0x04bb, 499, /* Ò» Òº */ + 0x04bd, 499, /* Ò½ Ò¼ */ + 0x04bf, 499, /* Ò¿ Ò¾ */ + 0x04c2, 499, /* Ó‚ Ó */ + 0x04c4, 499, /* Ó„ Óƒ */ + 0x04c8, 499, /* Óˆ Ó‡ */ + 0x04cc, 499, /* ÓŒ Ó‹ */ + 0x04d1, 499, /* Ó‘ Ó */ + 0x04d3, 499, /* Ó“ Ó’ */ + 0x04d5, 499, /* Ó• Ó” */ + 0x04d7, 499, /* Ó— Ó– */ + 0x04d9, 499, /* Ó™ Ó˜ */ + 0x04db, 499, /* Ó› Óš */ + 0x04dd, 499, /* Ó Óœ */ + 0x04df, 499, /* ÓŸ Óž */ + 0x04e1, 499, /* Ó¡ Ó */ + 0x04e3, 499, /* Ó£ Ó¢ */ + 0x04e5, 499, /* Ó¥ Ó¤ */ + 0x04e7, 499, /* Ó§ Ó¦ */ + 0x04e9, 499, /* Ó© Ó¨ */ + 0x04eb, 499, /* Ó« Óª */ + 0x04ef, 499, /* Ó¯ Ó® */ + 0x04f1, 499, /* Ó± Ó° */ + 0x04f3, 499, /* Ó³ Ó² */ + 0x04f5, 499, /* Óµ Ó´ */ + 0x04f9, 499, /* Ó¹ Ó¸ */ + 0x1e01, 499, /* ḠḀ */ + 0x1e03, 499, /* ḃ Ḃ */ + 0x1e05, 499, /* ḅ Ḅ */ + 0x1e07, 499, /* ḇ Ḇ */ + 0x1e09, 499, /* ḉ Ḉ */ + 0x1e0b, 499, /* ḋ Ḋ */ + 0x1e0d, 499, /* ḠḌ */ + 0x1e0f, 499, /* ḠḎ */ + 0x1e11, 499, /* ḑ Ḡ*/ + 0x1e13, 499, /* ḓ Ḓ */ + 0x1e15, 499, /* ḕ Ḕ */ + 0x1e17, 499, /* ḗ Ḗ */ + 0x1e19, 499, /* ḙ Ḙ */ + 0x1e1b, 499, /* ḛ Ḛ */ + 0x1e1d, 499, /* ḠḜ */ + 0x1e1f, 499, /* ḟ Ḟ */ + 0x1e21, 499, /* ḡ Ḡ*/ + 0x1e23, 499, /* ḣ Ḣ */ + 0x1e25, 499, /* ḥ Ḥ */ + 0x1e27, 499, /* ḧ Ḧ */ + 0x1e29, 499, /* ḩ Ḩ */ + 0x1e2b, 499, /* ḫ Ḫ */ + 0x1e2d, 499, /* ḠḬ */ + 0x1e2f, 499, /* ḯ Ḯ */ + 0x1e31, 499, /* ḱ Ḱ */ + 0x1e33, 499, /* ḳ Ḳ */ + 0x1e35, 499, /* ḵ Ḵ */ + 0x1e37, 499, /* ḷ Ḷ */ + 0x1e39, 499, /* ḹ Ḹ */ + 0x1e3b, 499, /* ḻ Ḻ */ + 0x1e3d, 499, /* ḽ Ḽ */ + 0x1e3f, 499, /* ḿ Ḿ */ + 0x1e41, 499, /* á¹ á¹€ */ + 0x1e43, 499, /* ṃ Ṃ */ + 0x1e45, 499, /* á¹… Ṅ */ + 0x1e47, 499, /* ṇ Ṇ */ + 0x1e49, 499, /* ṉ Ṉ */ + 0x1e4b, 499, /* ṋ Ṋ */ + 0x1e4d, 499, /* ṠṌ */ + 0x1e4f, 499, /* ṠṎ */ + 0x1e51, 499, /* ṑ á¹ */ + 0x1e53, 499, /* ṓ á¹’ */ + 0x1e55, 499, /* ṕ á¹” */ + 0x1e57, 499, /* á¹— á¹– */ + 0x1e59, 499, /* á¹™ Ṙ */ + 0x1e5b, 499, /* á¹› Ṛ */ + 0x1e5d, 499, /* ṠṜ */ + 0x1e5f, 499, /* ṟ Ṟ */ + 0x1e61, 499, /* ṡ á¹ */ + 0x1e63, 499, /* á¹£ á¹¢ */ + 0x1e65, 499, /* á¹¥ Ṥ */ + 0x1e67, 499, /* á¹§ Ṧ */ + 0x1e69, 499, /* ṩ Ṩ */ + 0x1e6b, 499, /* ṫ Ṫ */ + 0x1e6d, 499, /* ṠṬ */ + 0x1e6f, 499, /* ṯ á¹® */ + 0x1e71, 499, /* á¹± á¹° */ + 0x1e73, 499, /* á¹³ á¹² */ + 0x1e75, 499, /* á¹µ á¹´ */ + 0x1e77, 499, /* á¹· á¹¶ */ + 0x1e79, 499, /* á¹¹ Ṹ */ + 0x1e7b, 499, /* á¹» Ṻ */ + 0x1e7d, 499, /* á¹½ á¹¼ */ + 0x1e7f, 499, /* ṿ á¹¾ */ + 0x1e81, 499, /* ẠẀ */ + 0x1e83, 499, /* ẃ Ẃ */ + 0x1e85, 499, /* ẅ Ẅ */ + 0x1e87, 499, /* ẇ Ẇ */ + 0x1e89, 499, /* ẉ Ẉ */ + 0x1e8b, 499, /* ẋ Ẋ */ + 0x1e8d, 499, /* ẠẌ */ + 0x1e8f, 499, /* ẠẎ */ + 0x1e91, 499, /* ẑ Ạ*/ + 0x1e93, 499, /* ẓ Ẓ */ + 0x1e95, 499, /* ẕ Ẕ */ + 0x1ea1, 499, /* ạ Ạ*/ + 0x1ea3, 499, /* ả Ả */ + 0x1ea5, 499, /* ấ Ấ */ + 0x1ea7, 499, /* ầ Ầ */ + 0x1ea9, 499, /* ẩ Ẩ */ + 0x1eab, 499, /* ẫ Ẫ */ + 0x1ead, 499, /* ẠẬ */ + 0x1eaf, 499, /* ắ Ắ */ + 0x1eb1, 499, /* ằ Ằ */ + 0x1eb3, 499, /* ẳ Ẳ */ + 0x1eb5, 499, /* ẵ Ẵ */ + 0x1eb7, 499, /* ặ Ặ */ + 0x1eb9, 499, /* ẹ Ẹ */ + 0x1ebb, 499, /* ẻ Ẻ */ + 0x1ebd, 499, /* ẽ Ẽ */ + 0x1ebf, 499, /* ế Ế */ + 0x1ec1, 499, /* ỠỀ */ + 0x1ec3, 499, /* ể Ể */ + 0x1ec5, 499, /* á»… Ễ */ + 0x1ec7, 499, /* ệ Ệ */ + 0x1ec9, 499, /* ỉ Ỉ */ + 0x1ecb, 499, /* ị Ị */ + 0x1ecd, 499, /* ỠỌ */ + 0x1ecf, 499, /* ỠỎ */ + 0x1ed1, 499, /* ố á» */ + 0x1ed3, 499, /* ồ á»’ */ + 0x1ed5, 499, /* ổ á»” */ + 0x1ed7, 499, /* á»— á»– */ + 0x1ed9, 499, /* á»™ Ộ */ + 0x1edb, 499, /* á»› Ớ */ + 0x1edd, 499, /* ỠỜ */ + 0x1edf, 499, /* ở Ở */ + 0x1ee1, 499, /* ỡ á» */ + 0x1ee3, 499, /* ợ Ợ */ + 0x1ee5, 499, /* ụ Ụ */ + 0x1ee7, 499, /* á»§ Ủ */ + 0x1ee9, 499, /* ứ Ứ */ + 0x1eeb, 499, /* ừ Ừ */ + 0x1eed, 499, /* ỠỬ */ + 0x1eef, 499, /* ữ á»® */ + 0x1ef1, 499, /* á»± á»° */ + 0x1ef3, 499, /* ỳ Ỳ */ + 0x1ef5, 499, /* ỵ á»´ */ + 0x1ef7, 499, /* á»· á»¶ */ + 0x1ef9, 499, /* ỹ Ỹ */ + 0x1f51, 508, /* ὑ á½™ */ + 0x1f53, 508, /* ὓ á½› */ + 0x1f55, 508, /* ὕ á½ */ + 0x1f57, 508, /* á½— Ὗ */ + 0x1fb3, 509, /* á¾³ á¾¼ */ + 0x1fc3, 509, /* ῃ ῌ */ + 0x1fe5, 507, /* á¿¥ Ῥ */ + 0x1ff3, 509 /* ῳ ῼ */ +] + +const rnums = [ + 0x0030, 0x0039, + 0x0660, 0x0669, + 0x06f0, 0x06f9, + 0x07c0, 0x07c9, + 0x0966, 0x096f, + 0x09e6, 0x09ef, + 0x0a66, 0x0a6f, + 0x0ae6, 0x0aef, + 0x0b66, 0x0b6f, + 0x0be6, 0x0bef, + 0x0c66, 0x0c6f, + 0x0ce6, 0x0cef, + 0x0d66, 0x0d6f, + 0x0e50, 0x0e59, + 0x0ed0, 0x0ed9, + 0x0f20, 0x0f29, + 0x1040, 0x1049, + 0x17e0, 0x17e9, + 0x1810, 0x1819, + 0x1946, 0x194f, + 0x19d0, 0x19d9, + 0x1b50, 0x1b59, + 0xff10, 0xff19, + 0x104a0, 0x104a9, + 0x1d7ce, 0x1d7ff +] + +/* + * upper case ranges + * 3rd col is conversion excess 500 + */ +const rtolower2 = [ + 0x0041, 0x005a, 532, /* A-Z a-z */ + 0x00c0, 0x00d6, 532, /* À-Ö à -ö */ + 0x00d8, 0x00de, 532, /* Ø-Þ ø-þ */ + 0x0189, 0x018a, 705, /* Ɖ-ÆŠ É–-É— */ + 0x018e, 0x018f, 702, /* ÆŽ-Æ É˜-É™ */ + 0x01b1, 0x01b2, 717, /* Ʊ-Ʋ ÊŠ-Ê‹ */ + 0x0388, 0x038a, 537, /* Έ-Ί Î-ί */ + 0x038e, 0x038f, 563, /* ÎŽ-Î Ï-ÏŽ */ + 0x0391, 0x03a1, 532, /* Α-Ρ α-Ï */ + 0x03a3, 0x03ab, 532, /* Σ-Ϋ σ-Ï‹ */ + 0x0401, 0x040c, 580, /* Ð-ÐŒ Ñ‘-Ñœ */ + 0x040e, 0x040f, 580, /* ÐŽ-Ð Ñž-ÑŸ */ + 0x0410, 0x042f, 532, /* Ð-Я а-Ñ */ + 0x0531, 0x0556, 548, /* Ô±-Õ– Õ¡-Ö† */ + 0x10a0, 0x10c5, 548, /* á‚ -Ⴥ áƒ-ჵ */ + 0x1f08, 0x1f0f, 492, /* Ἀ-á¼ á¼€-ἇ */ + 0x1f18, 0x1f1d, 492, /* Ἐ-á¼ á¼-ἕ */ + 0x1f28, 0x1f2f, 492, /* Ἠ-Ἧ á¼ -á¼§ */ + 0x1f38, 0x1f3f, 492, /* Ἰ-Ἷ á¼°-á¼· */ + 0x1f48, 0x1f4d, 492, /* Ὀ-á½ á½€-á½… */ + 0x1f68, 0x1f6f, 492, /* Ὠ-Ὧ á½ -á½§ */ + 0x1f88, 0x1f8f, 492, /* ᾈ-á¾ á¾€-ᾇ */ + 0x1f98, 0x1f9f, 492, /* ᾘ-ᾟ á¾-á¾— */ + 0x1fa8, 0x1faf, 492, /* ᾨ-ᾯ á¾ -á¾§ */ + 0x1fb8, 0x1fb9, 492, /* Ᾰ-á¾¹ á¾°-á¾± */ + 0x1fba, 0x1fbb, 426, /* Ὰ-á¾» á½°-á½± */ + 0x1fc8, 0x1fcb, 414, /* Ὲ-á¿‹ á½²-á½µ */ + 0x1fd8, 0x1fd9, 492, /* Ῐ-á¿™ á¿-á¿‘ */ + 0x1fda, 0x1fdb, 400, /* Ὶ-á¿› á½¶-á½· */ + 0x1fe8, 0x1fe9, 492, /* Ῠ-á¿© á¿ -á¿¡ */ + 0x1fea, 0x1feb, 388, /* Ὺ-á¿« ὺ-á½» */ + 0x1ff8, 0x1ff9, 372, /* Ὸ-Ό ὸ-á½¹ */ + 0x1ffa, 0x1ffb, 374, /* Ὼ-á¿» á½¼-á½½ */ + 0x2160, 0x216f, 516, /* â… -â…¯ â…°-â…¿ */ + 0x24b6, 0x24cf, 526, /* â’¶-â“ â“-â“© */ + 0xff21, 0xff3a, 532 /* A-Z ï½-z */ +] + +/* + * upper case singlets + * 2nd col is conversion excess 500 + */ +const rtolower1 = [ + 0x0100, 501, /* Ä€ Ä */ + 0x0102, 501, /* Ä‚ ă */ + 0x0104, 501, /* Ä„ Ä… */ + 0x0106, 501, /* Ć ć */ + 0x0108, 501, /* Ĉ ĉ */ + 0x010a, 501, /* ÄŠ Ä‹ */ + 0x010c, 501, /* ÄŒ Ä */ + 0x010e, 501, /* ÄŽ Ä */ + 0x0110, 501, /* Ä Ä‘ */ + 0x0112, 501, /* Ä’ Ä“ */ + 0x0114, 501, /* Ä” Ä• */ + 0x0116, 501, /* Ä– Ä— */ + 0x0118, 501, /* Ę Ä™ */ + 0x011a, 501, /* Äš Ä› */ + 0x011c, 501, /* Äœ Ä */ + 0x011e, 501, /* Äž ÄŸ */ + 0x0120, 501, /* Ä Ä¡ */ + 0x0122, 501, /* Ä¢ Ä£ */ + 0x0124, 501, /* Ĥ Ä¥ */ + 0x0126, 501, /* Ħ ħ */ + 0x0128, 501, /* Ĩ Ä© */ + 0x012a, 501, /* Ī Ä« */ + 0x012c, 501, /* Ĭ Ä */ + 0x012e, 501, /* Ä® į */ + 0x0130, 301, /* İ i */ + 0x0132, 501, /* IJ ij */ + 0x0134, 501, /* Ä´ ĵ */ + 0x0136, 501, /* Ķ Ä· */ + 0x0139, 501, /* Ĺ ĺ */ + 0x013b, 501, /* Ä» ļ */ + 0x013d, 501, /* Ľ ľ */ + 0x013f, 501, /* Ä¿ Å€ */ + 0x0141, 501, /* Å Å‚ */ + 0x0143, 501, /* Ń Å„ */ + 0x0145, 501, /* Å… ņ */ + 0x0147, 501, /* Ň ň */ + 0x014a, 501, /* ÅŠ Å‹ */ + 0x014c, 501, /* ÅŒ Å */ + 0x014e, 501, /* ÅŽ Å */ + 0x0150, 501, /* Å Å‘ */ + 0x0152, 501, /* Å’ Å“ */ + 0x0154, 501, /* Å” Å• */ + 0x0156, 501, /* Å– Å— */ + 0x0158, 501, /* Ř Å™ */ + 0x015a, 501, /* Åš Å› */ + 0x015c, 501, /* Åœ Å */ + 0x015e, 501, /* Åž ÅŸ */ + 0x0160, 501, /* Å Å¡ */ + 0x0162, 501, /* Å¢ Å£ */ + 0x0164, 501, /* Ť Å¥ */ + 0x0166, 501, /* Ŧ ŧ */ + 0x0168, 501, /* Ũ Å© */ + 0x016a, 501, /* Ū Å« */ + 0x016c, 501, /* Ŭ Å */ + 0x016e, 501, /* Å® ů */ + 0x0170, 501, /* Ű ű */ + 0x0172, 501, /* Ų ų */ + 0x0174, 501, /* Å´ ŵ */ + 0x0176, 501, /* Ŷ Å· */ + 0x0178, 379, /* Ÿ ÿ */ + 0x0179, 501, /* Ź ź */ + 0x017b, 501, /* Å» ż */ + 0x017d, 501, /* Ž ž */ + 0x0181, 710, /* Æ É“ */ + 0x0182, 501, /* Æ‚ ƃ */ + 0x0184, 501, /* Æ„ Æ… */ + 0x0186, 706, /* Ɔ É” */ + 0x0187, 501, /* Ƈ ƈ */ + 0x018b, 501, /* Æ‹ ÆŒ */ + 0x0190, 703, /* Æ É› */ + 0x0191, 501, /* Æ‘ Æ’ */ + 0x0193, 705, /* Æ“ É */ + 0x0194, 707, /* Æ” É£ */ + 0x0196, 711, /* Æ– É© */ + 0x0197, 709, /* Æ— ɨ */ + 0x0198, 501, /* Ƙ Æ™ */ + 0x019c, 711, /* Æœ ɯ */ + 0x019d, 713, /* Æ É² */ + 0x01a0, 501, /* Æ Æ¡ */ + 0x01a2, 501, /* Æ¢ Æ£ */ + 0x01a4, 501, /* Ƥ Æ¥ */ + 0x01a7, 501, /* Ƨ ƨ */ + 0x01a9, 718, /* Æ© ʃ */ + 0x01ac, 501, /* Ƭ Æ */ + 0x01ae, 718, /* Æ® ʈ */ + 0x01af, 501, /* Ư ư */ + 0x01b3, 501, /* Ƴ Æ´ */ + 0x01b5, 501, /* Ƶ ƶ */ + 0x01b7, 719, /* Æ· Ê’ */ + 0x01b8, 501, /* Ƹ ƹ */ + 0x01bc, 501, /* Ƽ ƽ */ + 0x01c4, 502, /* Ç„ dž */ + 0x01c5, 501, /* Ç… dž */ + 0x01c7, 502, /* LJ lj */ + 0x01c8, 501, /* Lj lj */ + 0x01ca, 502, /* ÇŠ ÇŒ */ + 0x01cb, 501, /* Ç‹ ÇŒ */ + 0x01cd, 501, /* Ç ÇŽ */ + 0x01cf, 501, /* Ç Ç */ + 0x01d1, 501, /* Ç‘ Ç’ */ + 0x01d3, 501, /* Ç“ Ç” */ + 0x01d5, 501, /* Ç• Ç– */ + 0x01d7, 501, /* Ç— ǘ */ + 0x01d9, 501, /* Ç™ Çš */ + 0x01db, 501, /* Ç› Çœ */ + 0x01de, 501, /* Çž ÇŸ */ + 0x01e0, 501, /* Ç Ç¡ */ + 0x01e2, 501, /* Ç¢ Ç£ */ + 0x01e4, 501, /* Ǥ Ç¥ */ + 0x01e6, 501, /* Ǧ ǧ */ + 0x01e8, 501, /* Ǩ Ç© */ + 0x01ea, 501, /* Ǫ Ç« */ + 0x01ec, 501, /* Ǭ Ç */ + 0x01ee, 501, /* Ç® ǯ */ + 0x01f1, 502, /* DZ dz */ + 0x01f2, 501, /* Dz dz */ + 0x01f4, 501, /* Ç´ ǵ */ + 0x01fa, 501, /* Ǻ Ç» */ + 0x01fc, 501, /* Ǽ ǽ */ + 0x01fe, 501, /* Ǿ Ç¿ */ + 0x0200, 501, /* È€ È */ + 0x0202, 501, /* È‚ ȃ */ + 0x0204, 501, /* È„ È… */ + 0x0206, 501, /* Ȇ ȇ */ + 0x0208, 501, /* Ȉ ȉ */ + 0x020a, 501, /* ÈŠ È‹ */ + 0x020c, 501, /* ÈŒ È */ + 0x020e, 501, /* ÈŽ È */ + 0x0210, 501, /* È È‘ */ + 0x0212, 501, /* È’ È“ */ + 0x0214, 501, /* È” È• */ + 0x0216, 501, /* È– È— */ + 0x0386, 538, /* Ά ά */ + 0x038c, 564, /* ÎŒ ÏŒ */ + 0x03e2, 501, /* Ï¢ Ï£ */ + 0x03e4, 501, /* Ϥ Ï¥ */ + 0x03e6, 501, /* Ϧ ϧ */ + 0x03e8, 501, /* Ϩ Ï© */ + 0x03ea, 501, /* Ϫ Ï« */ + 0x03ec, 501, /* Ϭ Ï */ + 0x03ee, 501, /* Ï® ϯ */ + 0x0460, 501, /* Ñ Ñ¡ */ + 0x0462, 501, /* Ñ¢ Ñ£ */ + 0x0464, 501, /* Ѥ Ñ¥ */ + 0x0466, 501, /* Ѧ ѧ */ + 0x0468, 501, /* Ѩ Ñ© */ + 0x046a, 501, /* Ѫ Ñ« */ + 0x046c, 501, /* Ѭ Ñ */ + 0x046e, 501, /* Ñ® ѯ */ + 0x0470, 501, /* Ѱ ѱ */ + 0x0472, 501, /* Ѳ ѳ */ + 0x0474, 501, /* Ñ´ ѵ */ + 0x0476, 501, /* Ѷ Ñ· */ + 0x0478, 501, /* Ѹ ѹ */ + 0x047a, 501, /* Ѻ Ñ» */ + 0x047c, 501, /* Ѽ ѽ */ + 0x047e, 501, /* Ѿ Ñ¿ */ + 0x0480, 501, /* Ò€ Ò */ + 0x0490, 501, /* Ò Ò‘ */ + 0x0492, 501, /* Ò’ Ò“ */ + 0x0494, 501, /* Ò” Ò• */ + 0x0496, 501, /* Ò– Ò— */ + 0x0498, 501, /* Ò˜ Ò™ */ + 0x049a, 501, /* Òš Ò› */ + 0x049c, 501, /* Òœ Ò */ + 0x049e, 501, /* Òž ÒŸ */ + 0x04a0, 501, /* Ò Ò¡ */ + 0x04a2, 501, /* Ò¢ Ò£ */ + 0x04a4, 501, /* Ò¤ Ò¥ */ + 0x04a6, 501, /* Ò¦ Ò§ */ + 0x04a8, 501, /* Ò¨ Ò© */ + 0x04aa, 501, /* Òª Ò« */ + 0x04ac, 501, /* Ò¬ Ò */ + 0x04ae, 501, /* Ò® Ò¯ */ + 0x04b0, 501, /* Ò° Ò± */ + 0x04b2, 501, /* Ò² Ò³ */ + 0x04b4, 501, /* Ò´ Òµ */ + 0x04b6, 501, /* Ò¶ Ò· */ + 0x04b8, 501, /* Ò¸ Ò¹ */ + 0x04ba, 501, /* Òº Ò» */ + 0x04bc, 501, /* Ò¼ Ò½ */ + 0x04be, 501, /* Ò¾ Ò¿ */ + 0x04c1, 501, /* Ó Ó‚ */ + 0x04c3, 501, /* Óƒ Ó„ */ + 0x04c7, 501, /* Ó‡ Óˆ */ + 0x04cb, 501, /* Ó‹ ÓŒ */ + 0x04d0, 501, /* Ó Ó‘ */ + 0x04d2, 501, /* Ó’ Ó“ */ + 0x04d4, 501, /* Ó” Ó• */ + 0x04d6, 501, /* Ó– Ó— */ + 0x04d8, 501, /* Ó˜ Ó™ */ + 0x04da, 501, /* Óš Ó› */ + 0x04dc, 501, /* Óœ Ó */ + 0x04de, 501, /* Óž ÓŸ */ + 0x04e0, 501, /* Ó Ó¡ */ + 0x04e2, 501, /* Ó¢ Ó£ */ + 0x04e4, 501, /* Ó¤ Ó¥ */ + 0x04e6, 501, /* Ó¦ Ó§ */ + 0x04e8, 501, /* Ó¨ Ó© */ + 0x04ea, 501, /* Óª Ó« */ + 0x04ee, 501, /* Ó® Ó¯ */ + 0x04f0, 501, /* Ó° Ó± */ + 0x04f2, 501, /* Ó² Ó³ */ + 0x04f4, 501, /* Ó´ Óµ */ + 0x04f8, 501, /* Ó¸ Ó¹ */ + 0x1e00, 501, /* Ḁ Ḡ*/ + 0x1e02, 501, /* Ḃ ḃ */ + 0x1e04, 501, /* Ḅ ḅ */ + 0x1e06, 501, /* Ḇ ḇ */ + 0x1e08, 501, /* Ḉ ḉ */ + 0x1e0a, 501, /* Ḋ ḋ */ + 0x1e0c, 501, /* Ḍ Ḡ*/ + 0x1e0e, 501, /* Ḏ Ḡ*/ + 0x1e10, 501, /* Ḡḑ */ + 0x1e12, 501, /* Ḓ ḓ */ + 0x1e14, 501, /* Ḕ ḕ */ + 0x1e16, 501, /* Ḗ ḗ */ + 0x1e18, 501, /* Ḙ ḙ */ + 0x1e1a, 501, /* Ḛ ḛ */ + 0x1e1c, 501, /* Ḝ Ḡ*/ + 0x1e1e, 501, /* Ḟ ḟ */ + 0x1e20, 501, /* Ḡḡ */ + 0x1e22, 501, /* Ḣ ḣ */ + 0x1e24, 501, /* Ḥ ḥ */ + 0x1e26, 501, /* Ḧ ḧ */ + 0x1e28, 501, /* Ḩ ḩ */ + 0x1e2a, 501, /* Ḫ ḫ */ + 0x1e2c, 501, /* Ḭ Ḡ*/ + 0x1e2e, 501, /* Ḯ ḯ */ + 0x1e30, 501, /* Ḱ ḱ */ + 0x1e32, 501, /* Ḳ ḳ */ + 0x1e34, 501, /* Ḵ ḵ */ + 0x1e36, 501, /* Ḷ ḷ */ + 0x1e38, 501, /* Ḹ ḹ */ + 0x1e3a, 501, /* Ḻ ḻ */ + 0x1e3c, 501, /* Ḽ ḽ */ + 0x1e3e, 501, /* Ḿ ḿ */ + 0x1e40, 501, /* á¹€ á¹ */ + 0x1e42, 501, /* Ṃ ṃ */ + 0x1e44, 501, /* Ṅ á¹… */ + 0x1e46, 501, /* Ṇ ṇ */ + 0x1e48, 501, /* Ṉ ṉ */ + 0x1e4a, 501, /* Ṋ ṋ */ + 0x1e4c, 501, /* Ṍ á¹ */ + 0x1e4e, 501, /* Ṏ á¹ */ + 0x1e50, 501, /* Ṡṑ */ + 0x1e52, 501, /* á¹’ ṓ */ + 0x1e54, 501, /* á¹” ṕ */ + 0x1e56, 501, /* á¹– á¹— */ + 0x1e58, 501, /* Ṙ á¹™ */ + 0x1e5a, 501, /* Ṛ á¹› */ + 0x1e5c, 501, /* Ṝ á¹ */ + 0x1e5e, 501, /* Ṟ ṟ */ + 0x1e60, 501, /* Ṡṡ */ + 0x1e62, 501, /* á¹¢ á¹£ */ + 0x1e64, 501, /* Ṥ á¹¥ */ + 0x1e66, 501, /* Ṧ á¹§ */ + 0x1e68, 501, /* Ṩ ṩ */ + 0x1e6a, 501, /* Ṫ ṫ */ + 0x1e6c, 501, /* Ṭ á¹ */ + 0x1e6e, 501, /* á¹® ṯ */ + 0x1e70, 501, /* á¹° á¹± */ + 0x1e72, 501, /* á¹² á¹³ */ + 0x1e74, 501, /* á¹´ á¹µ */ + 0x1e76, 501, /* á¹¶ á¹· */ + 0x1e78, 501, /* Ṹ á¹¹ */ + 0x1e7a, 501, /* Ṻ á¹» */ + 0x1e7c, 501, /* á¹¼ á¹½ */ + 0x1e7e, 501, /* á¹¾ ṿ */ + 0x1e80, 501, /* Ẁ Ạ*/ + 0x1e82, 501, /* Ẃ ẃ */ + 0x1e84, 501, /* Ẅ ẅ */ + 0x1e86, 501, /* Ẇ ẇ */ + 0x1e88, 501, /* Ẉ ẉ */ + 0x1e8a, 501, /* Ẋ ẋ */ + 0x1e8c, 501, /* Ẍ Ạ*/ + 0x1e8e, 501, /* Ẏ Ạ*/ + 0x1e90, 501, /* Ạẑ */ + 0x1e92, 501, /* Ẓ ẓ */ + 0x1e94, 501, /* Ẕ ẕ */ + 0x1ea0, 501, /* Ạạ */ + 0x1ea2, 501, /* Ả ả */ + 0x1ea4, 501, /* Ấ ấ */ + 0x1ea6, 501, /* Ầ ầ */ + 0x1ea8, 501, /* Ẩ ẩ */ + 0x1eaa, 501, /* Ẫ ẫ */ + 0x1eac, 501, /* Ậ Ạ*/ + 0x1eae, 501, /* Ắ ắ */ + 0x1eb0, 501, /* Ằ ằ */ + 0x1eb2, 501, /* Ẳ ẳ */ + 0x1eb4, 501, /* Ẵ ẵ */ + 0x1eb6, 501, /* Ặ ặ */ + 0x1eb8, 501, /* Ẹ ẹ */ + 0x1eba, 501, /* Ẻ ẻ */ + 0x1ebc, 501, /* Ẽ ẽ */ + 0x1ebe, 501, /* Ế ế */ + 0x1ec0, 501, /* Ề á» */ + 0x1ec2, 501, /* Ể ể */ + 0x1ec4, 501, /* Ễ á»… */ + 0x1ec6, 501, /* Ệ ệ */ + 0x1ec8, 501, /* Ỉ ỉ */ + 0x1eca, 501, /* Ị ị */ + 0x1ecc, 501, /* Ọ á» */ + 0x1ece, 501, /* Ỏ á» */ + 0x1ed0, 501, /* Ỡố */ + 0x1ed2, 501, /* á»’ ồ */ + 0x1ed4, 501, /* á»” ổ */ + 0x1ed6, 501, /* á»– á»— */ + 0x1ed8, 501, /* Ộ á»™ */ + 0x1eda, 501, /* Ớ á»› */ + 0x1edc, 501, /* Ờ á» */ + 0x1ede, 501, /* Ở ở */ + 0x1ee0, 501, /* Ỡỡ */ + 0x1ee2, 501, /* Ợ ợ */ + 0x1ee4, 501, /* Ụ ụ */ + 0x1ee6, 501, /* Ủ á»§ */ + 0x1ee8, 501, /* Ứ ứ */ + 0x1eea, 501, /* Ừ ừ */ + 0x1eec, 501, /* Ử á» */ + 0x1eee, 501, /* á»® ữ */ + 0x1ef0, 501, /* á»° á»± */ + 0x1ef2, 501, /* Ỳ ỳ */ + 0x1ef4, 501, /* á»´ ỵ */ + 0x1ef6, 501, /* á»¶ á»· */ + 0x1ef8, 501, /* Ỹ ỹ */ + 0x1f59, 492, /* á½™ ὑ */ + 0x1f5b, 492, /* á½› ὓ */ + 0x1f5d, 492, /* ὠὕ */ + 0x1f5f, 492, /* Ὗ á½— */ + 0x1fbc, 491, /* á¾¼ á¾³ */ + 0x1fcc, 491, /* ῌ ῃ */ + 0x1fec, 493, /* Ῥ á¿¥ */ + 0x1ffc, 491 /* ῼ ῳ */ +] + +/* + * title characters are those between + * upper and lower case. ie DZ Dz dz + */ +const rtotitle1 = [ + 0x01c4, 501, /* Ç„ Ç… */ + 0x01c6, 499, /* dž Ç… */ + 0x01c7, 501, /* LJ Lj */ + 0x01c9, 499, /* lj Lj */ + 0x01ca, 501, /* ÇŠ Ç‹ */ + 0x01cc, 499, /* ÇŒ Ç‹ */ + 0x01f1, 501, /* DZ Dz */ + 0x01f3, 499 /* dz Dz */ +] + +const findc = {c, t, n, nelt, ret + var p, m + + /* + we're processing in chunks of size + nelt, so 1 chunk is of length 'nelt' + */ + while n > 1 + m = n/2 + p = t[m*nelt:] + if c >= p[0] + t = p + n = n - m + else + n = m + ;; + ;; + + if t.len != 0 && c >= t[0] + ret# = t + -> true + else + -> false + ;; +} + + +const isalpha = {c + var l + + if isupper(c) || islower(c) + -> true + elif findc(c, ralpha2[:], ralpha2.len/2, 2, &l) + if (c >= l[0] && c <= l[1]) + -> true + ;; + elif findc(c, ralpha1[:], ralpha1.len, 1, &l) + if (c == l[0]) + -> true + ;; + ;; + -> false +} + +const isdigit = {c + -> c >= '0' && c <= '9' +} + +const isxdigit = {c + -> c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F' +} + +const isnum = {c + var l + + if findc(c, rnums[:], rnums.len/2, 2, &l) + if(c >= l[0] && c <= l[1]) + -> true + ;; + ;; + -> false +} + +const isalnum = {c + -> isalpha(c) || isnum(c) +} + +const isblank = {c + var l + var sl + var len + + l = rspace2[:] + sl = rspace2[:] + len = rspace2.len/2 + if findc(c, sl, len, 2, &l) + if(c >= l[0] && c <= l[1]) + -> true + ;; + ;; + -> false +} + +const isspace = {c + -> c == '\n' || isblank(c) +} + +const islower = {c + var l + + /* the first character in the toupper table is the lowercase char */ + if findc(c, rtoupper2[:], rtoupper2.len/3, 3, &l) + if (c >= l[0] && c <= l[1]) + -> true + ;; + elif findc(c, rtoupper1[:], rtoupper1.len/2, 2, &l) + if (c == l[0]) + -> true + ;; + ;; + -> false +} + +const isupper = {c + var l + + /* the first character in the tolower table is the uppercase char */ + if findc(c, rtolower2[:], rtolower2.len/3, 3, &l) + if (c >= l[0] && c <= l[1]) + -> true + ;; + elif findc(c, rtolower1[:], rtolower1.len/2, 2, &l) + if (c == l[0]) + -> true + ;; + ;; + -> false +} + +const istitle = {c + -> isupper(c) && islower(c) +} + +const tolower = {c + var l + + if findc(c, rtolower2[:], rtolower2.len/3, 3, &l) + if c >= l[0] && c <= l[1] + -> c + l[2] - 500; + ;; + elif findc(c, rtolower1[:], rtolower1.len/2, 2, &l) + if c == l[0] + -> c + l[1] - 500; + ;; + ;; + -> c +} + +const toupper = {c + var l + + if findc(c, rtoupper2[:], rtoupper2.len/3, 3, &l); + if c >= l[0] && c <= l[1] + -> c + l[2] - 500; + ;; + elif findc(c, rtoupper1[:], rtoupper1.len/2, 2, &l); + if c == l[0] + -> c + l[1] - 500; + ;; + ;; + -> c +} + +const totitle = {c + var l + + if findc(c, rtotitle1[:], rtotitle1.len/2, 2, &l); + if c == l[0] + -> c + l[1] - 500; + ;; + ;; + -> c +} + +generic charval = {c, base -> @a::(numeric,integral) + var v = -1 + + if c >= '0' && c <= '9' + v = (c - '0') castto(@a::(integral,numeric)) + elif c >= 'a' && c <= 'z' + v = (c - 'a' + 10) castto(@a::(integral,numeric)) + elif c >= 'A' && c <= 'Z' + v = (c - 'A' + 10) castto(@a::(integral,numeric)) + ;; + + if v < 0 || v > (base castto(@a::(integral,numeric))) + -> -1 + ;; + -> v +} diff --git a/lib/std/clear.myr b/lib/std/clear.myr new file mode 100644 index 0000000..c16c851 --- /dev/null +++ b/lib/std/clear.myr @@ -0,0 +1,12 @@ +use "slfill.use" +pkg std = + generic clear : (p : @a# -> void) +;; + +generic clear = {p : @a# + var bp + + bp = p castto(byte#) + slfill(bp[:sizeof(@a)], 0) +} + diff --git a/lib/std/cmp.myr b/lib/std/cmp.myr new file mode 100644 index 0000000..edc5fe3 --- /dev/null +++ b/lib/std/cmp.myr @@ -0,0 +1,54 @@ +use "extremum.use" +use "types.use" + +pkg std = + type order = union + `Before + `Equal + `After + ;; + + generic numcmp : (a : @a, b : @a -> order) + const strcmp : (a : byte[:], b : byte[:] -> order) + const strncmp : (a : byte[:], b : byte[:], n : size -> order) +;; + +generic numcmp = {a, b + if a < b + -> `Before + elif a == b + -> `Equal + else + -> `After + ;; +} + +const strcmp = {a, b + var l + var i + + l = min(a.len, b.len) + for i = 0; i < l; i++ + if a[i] < b[i] + -> `Before + elif a[i] > b[i] + -> `After + ;; + ;; + + if a.len < b.len + -> `Before + elif a.len > b.len + -> `After + else + -> `Equal + ;; + +} + +const strncmp = {a, b, n + a = a[:min(a.len, n)] + b = b[:min(b.len, n)] + -> strcmp(a, b) +} + diff --git a/lib/std/cstrconv.myr b/lib/std/cstrconv.myr new file mode 100644 index 0000000..fa9e0bf --- /dev/null +++ b/lib/std/cstrconv.myr @@ -0,0 +1,40 @@ +use "types.use" + +pkg std = + const cstrlen : (buf : byte[:] -> size) + const cstrconv : (buf : byte[:] -> byte[:]) + const cstrconvp : (p : byte# -> byte[:]) +;; + +const cstrconv = {buf + var i + + for i = 0; i < buf.len; i++ + if buf[i] == 0 + -> buf[:i] + ;; + ;; + -> buf +} + +const cstrconvp = {p + var i, base + + i = 0 + base = p castto(intptr) + while ((base + i) castto(byte#))# != 0 + i++ + ;; + -> p[:i] +} + +const cstrlen = {buf + var i + + for i = 0; i < buf.len; i++ + if buf[i] == 0 + break + ;; + ;; + -> i +} diff --git a/lib/std/dial+plan9.myr b/lib/std/dial+plan9.myr new file mode 100644 index 0000000..35d97e9 --- /dev/null +++ b/lib/std/dial+plan9.myr @@ -0,0 +1,165 @@ +use sys + +use "alloc.use" +use "die.use" +use "fmt.use" +use "option.use" +use "pathjoin.use" +use "result.use" +use "sleq.use" +use "strfind.use" +use "strstrip.use" +use "syswrap.use" +use "utf.use" + + +pkg std = + const dial : (dialstr : byte[:] -> result(fd, byte[:])) +;; + +const Maxpath = 512 + +const dial = {str + var netdir, proto, rem + + (netdir, proto, rem) = parsedial(str) + if netdir.len != 0 + -> csdial(netdir, proto, rem) + ;; + + match csdial("/net", proto, rem) + | `Ok fd: -> `Ok fd + | `Fail m: + -> csdial("/net.alt", proto, rem) + ;; +} + +const csdial = {netdir, proto, rem + var dir, clone, addr, csaddr + var ret, csfd, n + var buf : byte[Maxpath] + + /* Try using the connection server */ + dir = fmt("{}/cs", netdir) + csfd = open(dir, Ordwr) + if csfd < 0 + clone = fmt("{}/{}/clone", netdir, proto) + ret = call(clone, rem, netdir) + slfree(clone) + if ret == -1 + -> `Fail "unable to dial without cs" + else + -> `Ok ret + ;; + ;; + slfree(dir) + + csaddr = fmt("{}!{}", proto, rem) + if write(csfd, csaddr) < 0 + close(csfd) + -> `Fail "couldn't blah cs" + ;; + slfree(csaddr) + + seek(csfd, 0, 0) + while true + n = read(csfd, buf[:]) + if n <= 0 + break + ;; + + match strfind(buf[:n], " ") + | `None: continue + | `Some i: + clone = buf[:i] + addr = buf[i+1:n] + ;; + + ret = call(clone, addr, netdir) + if ret >= 0 + break + ;; + ;; + + close(csfd) + if ret < 0 + -> `Fail "unable to dial" + ;; + -> `Ok ret +} + +const call = {clone, addr, netdir + var namebuf : byte[Maxpath] + var databuf : byte[Maxpath] + var name, base, dpath + var cfd, datafd + var c, n + + datafd = -1 + c = nsclonestr(clone, netdir) + cfd = open(c, Ordwr) + if cfd < 0 + goto cleanup + ;; + + n = read(cfd, namebuf[:]) + if n < 0 + goto cleanup + ;; + fput(cfd, "connect {}", addr) + name = strstrip(namebuf[:n]) + match strrfind(c, "/") + | `None: die("there should be a '/' here\n") + | `Some i: base = c[:i] + ;; + dpath = bfmt(databuf[:], "{}/{}/data", base, name) + datafd = open(dpath, Ordwr) +:cleanup + close(cfd) + slfree(c) + -> datafd +} + +const nsclonestr = {clone, netdir + if decode(clone) == '#' || decode(clone) == '/' + match std.strfind(clone[1:], "/") + | `Some i: clone = clone[i+1:] + | `None: /* nothing */ + ;; + ;; + -> pathcat(netdir, clone) +} + +const parsedial = {str + var netdir, proto, rem, hd, tl + + netdir="" + proto = "" + rem = "" + match strfind(str, "!") + | `None: + proto = "net" + rem = str + | `Some sep: + hd = str[:sep] + tl = str[sep+1:] + if decode(hd) == '#' || decode(hd) == '/' + match strrfind(hd, "/") + | `Some idx: + netdir = hd[:idx] + proto = hd[idx+1:] + | `None: + netdir = "" + proto = hd + ;; + else + netdir = "" + proto = hd + + ;; + rem = tl + ;; + + -> (netdir, proto, rem) +} + diff --git a/lib/std/dial+posixy.myr b/lib/std/dial+posixy.myr new file mode 100644 index 0000000..13f0257 --- /dev/null +++ b/lib/std/dial+posixy.myr @@ -0,0 +1,147 @@ +use sys + +use "alloc.use" +use "chartype.use" +use "die.use" +use "endian.use" +use "hasprefix.use" +use "intparse.use" +use "ipparse.use" +use "option.use" +use "resolve.use" +use "result.use" +use "sleq.use" +use "strfind.use" +use "syswrap.use" +use "utf.use" + +pkg std = + const dial : (dialstr : byte[:] -> result(fd, byte[:])) +;; + +/* + a map from service name to a list of (port,proto) + pairs in order of preference +*/ +/* FIXME: implement +var services : htab(byte[:], [int, byte[:]][:])# +var inited = false +*/ + +/* takes a plan 9 style dial string */ +const dial = {str + var proto, host, port + var sa4 : sys.sockaddr_in + var sa6 : sys.sockaddr_in6 + var sa : sys.sockaddr# + var sock + + match parsedial(str) + | `Ok val: (proto, host, port) = val + | `Fail m: -> `Fail m + ;; + + match getaddr(host) + | `Ipv4 bits: + sa4.fam = sys.Afinet + sa4.addr = bits + sa4.port = hosttonet(port) + sa = &sa4 castto(sys.sockaddr#) + | `Ipv6 bits: + sa6.fam = sys.Afinet6 + sa6.addr = bits + sa6.port = hosttonet(port) + sa = &sa6 castto(sys.sockaddr#) + ;; + sock = sys.socket(sa.fam, proto, 0) + + if sock < 0 + -> `Fail "failed to connect to socket" + ;; + var err + err = sys.connect(sock, sa, sizeof(sys.sockaddr_in)) + if err < 0 + sys.close(sock) + -> `Fail "Failed to bind socket" + ;; + + -> `Ok (sock castto(fd)) +} + +const parsedial = {str + var proto, host, port + var socktype, portnum + + (proto, str) = nameseg(str) + (host, str) = nameseg(str) + (port, str) = nameseg(str) + + if proto.len == 0 + -> `Fail "missing proto" + elif host.len == 0 + -> `Fail "missing host" + elif port.len == 0 + -> `Fail "missing port" + ;; + + if sleq(proto, "net") + -> `Fail "net wildcard proto not yet supported\n" + elif sleq(proto, "unix") + -> `Fail "net unix proto not yet supported\n" + elif sleq(proto, "tcp") + socktype = sys.Sockstream + elif sleq(proto, "udp") + socktype = sys.Sockdgram + ;; + + match parseport(port) + | `Some n: portnum = n + | `None: -> `Fail "bad port" + ;; + + -> `Ok (socktype, host, portnum) +} + +const parseport = {port + match intparse(port) + | `Some n: -> `Some n + | `None: + /* a small number of hardcoded ports */ + if sleq(port, "http") + -> `Some 80 + elif sleq(port, "https") + -> `Some 443 + elif sleq(port, "ircd") + -> `Some 6667 + elif sleq(port, "dns") + -> `Some 53 + ;; + ;; + -> `None +} + +const getaddr = {addr + var ip + + match ipparse(addr) + | `Some a: ip = a + | `None: + match resolve(addr) + | `Ok hi: + ip = hi[0].addr + slfree(hi) + | `Fail m: + ;; + ;; + -> ip +} + +const nameseg = {str + match strfind(str, "!") + | `Some idx: + -> (str[:idx], str[idx+1:]) + | `None: + -> (str, "") + ;; +} + diff --git a/lib/std/die.myr b/lib/std/die.myr new file mode 100644 index 0000000..87135f1 --- /dev/null +++ b/lib/std/die.myr @@ -0,0 +1,19 @@ +use "syswrap.use" +use "types.use" + +pkg std = + $noret const die : (msg : byte[:] -> void) + const assert : (cond : bool, msg : byte[:] -> void) +;; + +const die = {msg + write(2, msg) + suicide() +} + +const assert = {cond, msg + if !cond + die(msg) + ;; +} + diff --git a/lib/std/dir+freebsd.myr b/lib/std/dir+freebsd.myr new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/std/dir+freebsd.myr diff --git a/lib/std/dir+linux.myr b/lib/std/dir+linux.myr new file mode 100644 index 0000000..60ef6f9 --- /dev/null +++ b/lib/std/dir+linux.myr @@ -0,0 +1,66 @@ +use sys + +use "alloc.use" +use "die.use" +use "option.use" +use "result.use" +use "slcp.use" +use "sldup.use" +use "types.use" + +pkg std = + type dir = struct + fd : sys.fd + buf : byte[16384] + len : int64 + off : int64 + ;; + + const diropen : (p : byte[:] -> std.result(dir#, byte[:])) + const dirread : (d : dir# -> std.option(byte[:])) + const dirclose : (d : dir# -> void) +;; + +const Direntoverhead = 20 + +const diropen = {p + var fd + var dir + + fd = sys.open(p, sys.Ordonly | sys.Odir) + if fd < 0 + -> `Fail "couldn't open directory" + ;; + dir = zalloc() + dir.fd = fd + -> `Ok dir +} + +const dirread = {d + var len + var dent + var namelen + + if d.off >= d.len + len = sys.getdents64(d.fd, d.buf[:]) + if len <= 0 + -> `None + ;; + d.len = len + d.off = 0 + ;; + + dent = &d.buf[d.off] castto(sys.dirent64#) + namelen = 0 + d.off += dent.reclen castto(int64) + while dent.name[namelen] != 0 + namelen++ + ;; + -> `Some sldup(dent.name[:namelen]) +} + +const dirclose = {d + sys.close(d.fd) + free(d) +} + diff --git a/lib/std/dir+osx.myr b/lib/std/dir+osx.myr new file mode 100644 index 0000000..28ef26b --- /dev/null +++ b/lib/std/dir+osx.myr @@ -0,0 +1,60 @@ +use sys + +use "alloc.use" +use "die.use" +use "option.use" +use "result.use" +use "slcp.use" +use "sldup.use" +use "types.use" + +pkg std = + type dir = struct + fd : sys.fd + buf : byte[16384] + len : int64 + off : int64 + base : int64 + ;; + + const diropen : (p : byte[:] -> std.result(dir#, byte[:])) + const dirread : (d : dir# -> std.option(byte[:])) + const dirclose : (d : dir# -> void) +;; + +const diropen = {p + var fd + var dir + + fd = sys.open(p, sys.Ordonly | sys.Odir) + if fd < 0 + -> `Fail "couldn't open directory" + ;; + dir = zalloc() + dir.fd = fd + -> `Ok dir +} + +const dirread = {d + var len + var dent + + if d.off >= d.len + len = sys.getdirentries64(d.fd, d.buf[:], &d.base) + if len <= 0 + -> `None + ;; + d.len = len + d.off = 0 + ;; + + dent = &d.buf[d.off] castto(sys.dirent64#) + d.off += dent.reclen castto(int64) + -> `Some sldup(dent.name[:dent.namlen]) +} + +const dirclose = {d + sys.close(d.fd) + free(d) +} + diff --git a/lib/std/dir+plan9.myr b/lib/std/dir+plan9.myr new file mode 100644 index 0000000..41a579f --- /dev/null +++ b/lib/std/dir+plan9.myr @@ -0,0 +1,66 @@ +use sys + +use "alloc.use" +use "die.use" +use "option.use" +use "result.use" +use "slcp.use" +use "sldup.use" +use "syswrap.use" +use "types.use" + +pkg std = + type dir = struct + fd : fd + buf : byte[65536] /* a big big, but at least it will always hold a directory entry... */ + len : int64 + off : int64 + ;; + + const diropen : (p : byte[:] -> std.result(dir#, byte[:])) + const dirread : (d : dir# -> std.option(byte[:])) + const dirclose : (d : dir# -> void) +;; + +const diropen = {p + var fd + var dir + + fd = open(p, Ordonly) + if fd < 0 + -> `Fail "couldn't open directory" + ;; + + dir = zalloc() + dir.fd = fd + -> `Ok dir +} + + +const dirread = {d + var len : int64, name, base, namelen, dirlen + + /* NB: On Plan 9, read(2) will always return whole directory entries */ + if d.off >= d.len + len = read(d.fd, d.buf[:]) castto(int64) + if len <= 0 + -> `None + ;; + d.len = len + d.off = 0 + ;; + + namelen = (d.buf[d.off + Stringsoff] castto(int64)) | \ + ((d.buf[d.off + Stringsoff + 1] castto(int64)) << 8) + base = d.off + Stringsoff + 2 + dirlen = (d.buf[d.off] castto(int64)) | \ + ((d.buf[d.off + 1] castto(int64)) << 8) + name = d.buf[base:base + namelen] + d.off += dirlen + 2 + -> `Some std.sldup(name) +} + +const dirclose = {d + close(d.fd) + free(d) +} diff --git a/lib/std/dirname.myr b/lib/std/dirname.myr new file mode 100644 index 0000000..5e80771 --- /dev/null +++ b/lib/std/dirname.myr @@ -0,0 +1,37 @@ +use "alloc.use" +use "slcp.use" +use "die.use" +use "sldup.use" +use "strfind.use" +use "option.use" + +pkg std = + const dirname : (p : byte[:] -> byte[:]) + const basename : (p : byte[:] -> byte[:]) +;; + +const dirname = {p + match std.strrfind(p, "/") + | `std.Some idx: + -> std.sldup(p[:idx]) + | `std.None: + -> std.sldup(".") + ;; +} + +const basename = {p +:again + if p.len == 0 + -> std.sldup(".") + ;; + + match std.strrfind(p, "/") + | `std.Some idx: + if idx == p.len - 1 + goto again + ;; + -> std.sldup(p[idx+1:]) + | `std.None: + -> std.sldup(p) + ;; +} diff --git a/lib/std/endian.myr b/lib/std/endian.myr new file mode 100644 index 0000000..8bac74f --- /dev/null +++ b/lib/std/endian.myr @@ -0,0 +1,32 @@ +pkg std = + generic hosttonet : (v : @a -> @a) + generic nettohost : (v : @a -> @a) +;; + +/* FIXME: we only support little endian platforms right now, + so we assume a little endian machine. FIX THIS. */ +generic hosttonet = {v : @a::(integral,numeric) + var i + var ret + + ret = 0 + for i = 0; i < sizeof(@a); i++ + ret <<= 8 + ret |= v & 0xff + v >>= 8 + ;; + -> ret +} + +generic nettohost = {v : @a::(integral,numeric) + var i + var ret + + ret = 0 + for i = 0; i < sizeof(@a); i++ + ret <<= 8 + ret |= v & 0xff + v >>= 8 + ;; + -> ret +} diff --git a/lib/std/env+plan9.myr b/lib/std/env+plan9.myr new file mode 100644 index 0000000..4a95ed7 --- /dev/null +++ b/lib/std/env+plan9.myr @@ -0,0 +1,56 @@ +use sys + +use "alloc.use" +use "die.use" +use "extremum.use" +use "fmt.use" +use "option.use" +use "result.use" +use "slcp.use" +use "sldup.use" +use "sleq.use" +use "slpush.use" +use "slurp.use" + +pkg std = + const getenv : (name : byte[:] -> option(byte[:])) + const getenvv : (name : byte[:], default : byte[:] -> byte[:]) +;; + +var envkey : byte[:][:] +var envval : byte[:][:] + +const envfind = {key + var i + for i = 0; i < envkey.len; i++ + if std.sleq(envkey[i], key) + -> `Some envval[i] + ;; + ;; + -> `None +} + +const getenv = {name + var buf : byte[128] + var s + + match envfind(name) + | `Some val: -> `Some val + | `None: + s = bfmt(buf[:], "/env/{}", name) + match std.slurp(s) + | `Fail m: -> `None + | `Ok data: + envkey = slpush(envkey, sldup(name)) + envval = slpush(envval, data) + -> `Some data + ;; + ;; +} + +const getenvv = {name, default + match getenv(name) + | `Some val: -> val + | `None: -> default + ;; +} diff --git a/lib/std/env+posixy.myr b/lib/std/env+posixy.myr new file mode 100644 index 0000000..d7b0e5e --- /dev/null +++ b/lib/std/env+posixy.myr @@ -0,0 +1,28 @@ +use sys + +use "extremum.use" +use "option.use" +use "sleq.use" + +pkg std = + const getenv : (name : byte[:] -> option(byte[:])) + const getenvv : (name : byte[:], default : byte[:] -> byte[:]) +;; + +const getenv = {name + var n + for env in sys.__environment + n = min(name.len, env.len) + if sleq(name, env[:n]) && sleq(env[n:n+1], "=") + -> `Some env[n+1:] + ;; + ;; + -> `None +} + +const getenvv = {name, default + match getenv(name) + | `Some v: -> v + | `None: -> default + ;; +} diff --git a/lib/std/errno+plan9.myr b/lib/std/errno+plan9.myr new file mode 100644 index 0000000..c911349 --- /dev/null +++ b/lib/std/errno+plan9.myr @@ -0,0 +1,6 @@ +pkg std = + type errno = int + const Erange : errno = 1 + const Emisc : errno = 2 + const Eexist : errno = 3 +;; diff --git a/lib/std/errno.myr b/lib/std/errno.myr new file mode 100644 index 0000000..c14c469 --- /dev/null +++ b/lib/std/errno.myr @@ -0,0 +1,40 @@ +use sys + +pkg std = + type errno = int + + const Eperm : errno = sys.Eperm castto(errno) + const Enoent : errno = sys.Enoent castto(errno) + const Esrch : errno = sys.Esrch castto(errno) + const Eintr : errno = sys.Eintr castto(errno) + const Eio : errno = sys.Eio castto(errno) + const Enxio : errno = sys.Enxio castto(errno) + const E2big : errno = sys.E2big castto(errno) + const Enoexec : errno = sys.Enoexec castto(errno) + const Ebadf : errno = sys.Ebadf castto(errno) + const Echild : errno = sys.Echild castto(errno) + const Eagain : errno = sys.Eagain castto(errno) + const Enomem : errno = sys.Enomem castto(errno) + const Eacces : errno = sys.Eacces castto(errno) + const Efault : errno = sys.Efault castto(errno) + const Enotblk : errno = sys.Enotblk castto(errno) + const Ebusy : errno = sys.Ebusy castto(errno) + const Eexist : errno = sys.Eexist castto(errno) + const Exdev : errno = sys.Exdev castto(errno) + const Enodev : errno = sys.Enodev castto(errno) + const Enotdir : errno = sys.Enotdir castto(errno) + const Eisdir : errno = sys.Eisdir castto(errno) + const Einval : errno = sys.Einval castto(errno) + const Enfile : errno = sys.Enfile castto(errno) + const Emfile : errno = sys.Emfile castto(errno) + const Enotty : errno = sys.Enotty castto(errno) + const Etxtbsy : errno = sys.Etxtbsy castto(errno) + const Efbig : errno = sys.Efbig castto(errno) + const Enospc : errno = sys.Enospc castto(errno) + const Espipe : errno = sys.Espipe castto(errno) + const Erofs : errno = sys.Erofs castto(errno) + const Emlink : errno = sys.Emlink castto(errno) + const Epipe : errno = sys.Epipe castto(errno) + const Edom : errno = sys.Edom castto(errno) + const Erange : errno = sys.Erange castto(errno) +;; diff --git a/lib/std/execvp.myr b/lib/std/execvp.myr new file mode 100644 index 0000000..38d9fc5 --- /dev/null +++ b/lib/std/execvp.myr @@ -0,0 +1,57 @@ +use "alloc.use" +use "env.use" +use "fmt.use" +use "option.use" +use "strfind.use" +use "strsplit.use" +use "syswrap.use" + +pkg std = + const execvp : (cmd : byte[:], args : byte[:][:] -> int64) + const execvpe : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64) +;; + +const execvp = {cmd, args + var paths, binpath + var buf : byte[512] + + match strfind(cmd, "/") + | `Some _: + -> execv(cmd, args) + | `None: + paths = getpaths() + for p in paths + binpath = bfmt(buf[:], "{}/{}", p, cmd) + execv(binpath, args) + ;; + slfree(paths) + ;; + -> -1 +} + +const execvpe = {cmd, args, env + var paths, binpath + var buf : byte[512] + + match strfind(cmd, "/") + | `Some _: + -> execve(cmd, args, env) + | `None: + paths = getpaths() + for p in paths + binpath = bfmt(buf[:], "{}/{}", p, cmd) + execve(binpath, args, env) + ;; + slfree(paths) + ;; + -> -1 +} + +const getpaths = { + var path + match getenv("PATH") + | `Some p: path = p + | `None: path = "/usr/local/bin:/bin:/usr/bin" + ;; + -> strsplit(path, ":") +} diff --git a/lib/std/extremum.myr b/lib/std/extremum.myr new file mode 100644 index 0000000..9675915 --- /dev/null +++ b/lib/std/extremum.myr @@ -0,0 +1,40 @@ +pkg std = + generic min : (a : @a::numeric, b : @a::numeric -> @a::numeric) + generic max : (a : @a::numeric, b : @a::numeric -> @a::numeric) + generic clamp : (a : @a::numeric, min : @a::numeric, max : @a::numeric -> @a::numeric) + generic abs : (a : @a::numeric -> @a::numeric) +;; + +generic min = {a, b + if a < b + -> a + else + -> b + ;; +} + +generic max = {a, b + if a > b + -> a + else + -> b + ;; +} + +generic clamp = {a, min, max + if a < min + -> min + elif a > max + -> max + else + -> a + ;; +} + +generic abs = {a : @a::numeric + if a < (0 castto(@a::numeric)) + -> -a + else + -> a + ;; +} diff --git a/lib/std/fltbits.myr b/lib/std/fltbits.myr new file mode 100644 index 0000000..2f77ee9 --- /dev/null +++ b/lib/std/fltbits.myr @@ -0,0 +1,60 @@ +pkg std = + const flt64bits : (flt : flt64 -> int64) + const flt32bits : (flt : flt32 -> int32) + const flt64frombits : (bits : uint64 -> flt64) + const flt32frombits : (bits : uint32 -> flt32) + const flt64explode : (flt : flt64 -> (bool, int64, int64)) + const flt32explode : (flt : flt32 -> (bool, int32, int32)) +;; + +const flt64bits = {flt; -> (&flt castto(int64#))#} +const flt32bits = {flt; -> (&flt castto(int32#))#} +const flt64frombits = {bits; -> (&bits castto(flt64#))#} +const flt32frombits = {bits; -> (&bits castto(flt32#))#} + +const flt64explode = {flt + var bits, isneg, mant, exp + + bits = flt64bits(flt) + isneg = (bits >> 63) != 0 /* msb is sign bit */ + exp = (bits >> 52) & 0x7ff /* exp is in bits [52..63] */ + mant = bits & ((1l << 52) - 1) /* msb is in bits [..51] */ + + /* add back the implicit bit if this is not a denormal */ + if exp != 0 + mant |= 1l << 52 + else + exp = 1 + ;; + /* + adjust for exponent bias. nb: because we are + treating the mantissa as m.0 instead of 0.m, + our exponent bias needs to be offset by the + size of m + */ + -> (isneg, mant, exp) +} + +const flt32explode = {flt + var bits, isneg, mant, exp + + bits = flt32bits(flt) + isneg = (bits >> 31) != 0 /* msb is sign bit */ + exp = (bits >> 22) & 0xff /* exp is in bits [23..30] */ + mant = bits & ((1 << 22) - 1) /* msb is in bits [0..22] */ + + /* add back the implicit bit if this is not a denormal */ + if exp != 0 + mant |= 1 << 22 + else + exp = 1 + ;; + /* + adjust for exponent bias. nb: because we are + treating the mantissa as m.0 instead of 0.m, + our exponent bias needs to be offset by the + size of m + */ + -> (isneg, mant, exp) +} + diff --git a/lib/std/fltfmt.myr b/lib/std/fltfmt.myr new file mode 100644 index 0000000..395ade4 --- /dev/null +++ b/lib/std/fltfmt.myr @@ -0,0 +1,239 @@ +use "alloc.use" +use "bigint.use" +use "die.use" +use "extremum.use" +use "fltbits.use" +use "slpush.use" +use "strbuf.use" +use "types.use" +use "utf.use" + +pkg std = + pkglocal const MNormal = 0 + pkglocal const MAbsolute = 1 + pkglocal const MRelative = 2 + + pkglocal const flt64bfmt : (sb : strbuf#, val : flt64, mode : int, precision : int -> void) + pkglocal const flt32bfmt : (sb : strbuf#, val : flt32, mode : int, precision : int -> void) +;; + +const Dblbias = 1023 +const Fltbias = 127 + +const flt64bfmt = {sb, val, mode, precision + var isneg, exp, mant + + (isneg, mant, exp) = flt64explode(val) + dragon4(sb, isneg, mant, (exp - 52) castto(int64), Dblbias, mode, precision) +} + +const flt32bfmt = {sb, val, mode, precision + var isneg, exp, mant + + (isneg, mant, exp) = flt32explode(val) + dragon4(sb, isneg, mant castto(int64), (exp - 52) castto(int64), Fltbias, mode, precision) +} + +/* +sb: output buffer +e: exponent +p: precision +f: mantissa + +flting value: x = f^(e - p) +*/ +const dragon4 = {sb, isneg, f, e, p, mode, cutoff + var r, s, t, u, v, y + var udig + var mm, mp /* margins above and below */ + var roundup + var low, high + var k, n + var a, i + + /* if we have zero for the mantissa, we can return early */ + n = 0 + if isneg + sbputs(sb, "-") + ;; + if f == 0 + sbputs(sb, "0.0") + ;; + + /* initialize */ + roundup = false + r = mkbigint(f) + r = bigshli(r, max(e - p, 0)) + s = bigshli(mkbigint(1), max(0, -(e - p))) + mm = bigshli(mkbigint(1), max((e - p), 0)) + mp = bigdup(mm) + + /* fixup: unequal gaps */ + t = mkbigint(1) + bigshli(t, p - 1) + if bigeqi(t, f) + bigshli(mp, 1) + bigshli(r, 1) + bigshli(s, 1) + ;; + bigfree(t) + + k = 0 + while true + /* r < ceil(s/b) */ + t = bigdup(s) + bigaddi(t, 9) + bigdivi(t, 10) + match bigcmp(r, t) + | `Before: + k-- + bigmuli(r, 10) + bigmuli(mm, 10) + bigmuli(mp, 10) + | _: + bigfree(t) + break + ;; + bigfree(t) + ;; + + while true + t = bigdup(r) + bigshli(t, 1) + bigadd(t, mp) + while true + u = bigdup(s) + bigshli(u, 1) + match bigcmp(t, u) + | `Before: + bigfree(u) + break + | _: + k++ + bigmuli(s, 10) + bigfree(u) + ;; + ;; + if mode == MNormal + cutoff = k + else + if mode == MRelative + cutoff += k - 1 + ;; + /* common between relative and absolute */ + a = cutoff - k - 1 + y = bigdup(s) + if a < 0 + for i = 0; i < a; i++ + bigmuli(y, 10) + ;; + else + for i = 0; i < -a; i++ + bigaddi(y, 9) + bigdivi(y, 10) + ;; + ;; + match bigcmp(y, mm) + | `Before: /* nothing */ + | _: + bigfree(mm) + mm = y + ;; + match bigcmp(y, mp) + | `Before: /* nothing */ + | _: + bigfree(mp) + mp = y + roundup = true + ;; + ;; + u = bigdup(s) + bigshli(u, 1) + match bigcmp(t, u) + | `Before: + bigfree(t) + bigfree(u) + break + | _: + ;; + ;; + + if k <= 0 + sbputs(sb, "0.") + ;; + while true + k-- + bigmuli(r, 10) + u = bigdup(r); + bigdiv(u, s) + + bigmod(r, s) + bigmuli(mm, 10) + bigmuli(mp, 10) + + low = false + t = bigdup(r) + bigshli(t, 1) + match bigcmp(t, mm) + | `Before: low = true + | _: + ;; + bigfree(t) + + v = bigdup(r) + bigshli(v, 1) + t = bigdup(s) + bigshli(t, 1) + bigsub(t, mp) + match bigcmp(v, t) + | `After: high = true + | `Equal: high = roundup + | `Before: high = false + ;; + bigfree(v) + bigfree(t) + if low || high || k == cutoff + break + ;; + format(sb, lowdig(u), k) + bigfree(u) + ;; + + /* format the last digit */ + udig = lowdig(u) + if low && !high + format(sb, udig, k) + elif high && !low + format(sb, udig + 1, k) + else + bigmuli(r, 2) + match bigcmp(r, s) + | `Before: format(sb, udig, k) + | `Equal: format(sb, udig, k) + | `After: format(sb, udig + 1, k) + ;; + ;; + -> n +} + +const lowdig = {u + if u.dig.len > 0 + -> u.dig[0] + ;; + -> 0 +} + +const format = {sb, d, k + const dig = "0123456789" + var i + + if k < 0 + for i = 0; i < -k - 1; i++ + sbputs(sb, "0") + ;; + ;; + sbputb(sb, dig[d]) + if k == 0 + sbputs(sb, ".") + ;; +} diff --git a/lib/std/fmt.myr b/lib/std/fmt.myr new file mode 100644 index 0000000..b786e98 --- /dev/null +++ b/lib/std/fmt.myr @@ -0,0 +1,499 @@ +use "alloc.use" +use "chartype.use" +use "die.use" +use "extremum.use" +use "fltfmt.use" +use "hashfuncs.use" +use "hasprefix.use" +use "htab.use" +use "introspect.use" +use "intparse.use" +use "option.use" +use "sleq.use" +use "slpush.use" +use "strbuf.use" +use "strfind.use" +use "strsplit.use" +use "syswrap-ss.use" +use "syswrap.use" +use "types.use" +use "utf.use" +use "varargs.use" + +pkg std = + /* write to fd */ + const put : (fmt : byte[:], args : ... -> size) + const fput : (fd : fd, fmt : byte[:], args : ... -> size) + const putv : (fmt : byte[:], ap : valist# -> size) + const fputv : (fd : fd, fmt : byte[:], ap : valist# -> size) + + /* write to buffer */ + const fmt : (fmt : byte[:], args : ... -> byte[:]) + const fmtv : (fmt : byte[:], ap : valist# -> byte[:]) + const bfmt : (buf : byte[:], fmt : byte[:], args : ... -> byte[:]) + const bfmtv : (buf : byte[:], fmt : byte[:], ap : valist# -> byte[:]) + + /* write to strbuf */ + const sbfmt : (buf : strbuf#, fmt : byte[:], args : ... -> size) + const sbfmtv : (buf : strbuf#, fmt : byte[:], ap : valist# -> size) + + /* add a formatter function */ + const fmtinstall : (ty : byte[:], \ + fn : (sb : strbuf#, ap : valist#, opts : (byte[:],byte[:])[:] -> void), \ + optdesc : (byte[:], bool)[:] \ + -> void) + + $noret const fatal : (fmt : byte[:], args : ... -> void) + $noret const fatalv : (fmt : byte[:], ap : valist# -> void) +;; + +const __init__ = { + fmtmap = mkht(strhash, streq) +} + +type fmtdesc = struct + fn : (sb : strbuf#, ap : valist#, opts : (byte[:],byte[:])[:] -> void) + optdesc : (byte[:], bool)[:] +;; + +/* same as 'put', but exits the program after printing */ +const fatal = {fmt, args + var ap + + ap = vastart(&args) + putv(fmt, &ap) + exit(1) +} + +/* same as 'putv', but exits the program after printing */ +const fatalv = {fmt, ap + putv(fmt, ap) + exit(1) +} + +var fmtmap : htab(byte[:], fmtdesc)# + +const fmtinstall = {ty, fn, optdesc + htput(fmtmap, ty, [.fn=fn, .optdesc=optdesc]) +} + +const put = {fmt, args + var ap + + ap = vastart(&args) + -> fputv(1, fmt, &ap) +} + +const putv = {fmt, ap + -> fputv(1, fmt, ap) +} + +const fput = {fd, fmt, args + var ap + + ap = vastart(&args) + -> fputv(fd, fmt, &ap) +} + +const fputv = {fd, fmt, ap + var sb, s + + sb = mksb() + sbfmtv(sb, fmt, ap) + s = sbfin(sb) + -> writeall(fd, s) +} + +const fmt = {fmt, args + var ap + + ap = vastart(&args) + -> fmtv(fmt, &ap) +} + +const fmtv = {fmt, ap + var sb + + sb = mksb() + sbfmtv(sb, fmt, ap) + -> sbfin(sb) +} + +const bfmt = {buf, fmt, args + var ap + + ap = vastart(&args) + -> bfmtv(buf, fmt, &ap) +} + +const bfmtv = {buf, fmt, ap + var sb + + sb = mkbufsb(buf) + sbfmtv(sb, fmt, ap) + -> sbfin(sb) +} + +const sbfmt = {sb, fmt, args + var ap + + ap = vastart(&args) + -> sbfmtv(sb, fmt, &ap) +} + +const sbfmtv = {sb, fmt, ap -> size + var nfmt, nparams, pl, orig + var c, params, ty + + orig = fmt + nparams = ap.tc.nelt + nfmt = 0 + while fmt.len != 0 + (c, fmt) = striter(fmt) + match c + | '{': + if decode(fmt) == '{' + (c, fmt) = striter(fmt) + sbputc(sb, '{') + else + (params, fmt) = getparams(fmt) + nfmt++ + if nfmt > nparams + die("too few params for fmt\n") + ;; + + ty = vatype(ap) + match htget(fmtmap, ty) + | `Some f: + pl = parseparams(params, f.optdesc) + f.fn(sb, ap, pl) + std.slfree(pl) + | `None: + fallbackfmt(sb, params, ty, ap) + ;; + ;; + | '}': + if decode(fmt) == '}' + sbputc(sb, '}') + ;; + | chr: + sbputc(sb, chr) + ;; +:fmtdone + ;; + if nfmt != nparams + write(1, orig) + die("too many params for fmt\n") + ;; + -> sb.len +} + +const parseparams = {paramstr, optdesc + var params, opts + var o, a, ha : bool, gotarg : bool + + opts = [][:] + params = strsplit(paramstr, ",") + for p in params + /* parse out the key/value pair */ + match std.strfind(p, "=") + | `std.Some idx: + o = p[:idx] + a = p[idx+1:] + gotarg = true + | `std.None: + o = p + a = "" + gotarg = false + ;; + + /* verify and add the arg */ + for (opt, hasarg) in optdesc + if !std.sleq(opt, o) + continue + ;; + ha = hasarg + if ha == gotarg + opts = std.slpush(opts, (o, a)) + else + std.fatal("invalid option {}", o) + ;; + ;; + ;; + slfree(params) + -> opts +} + + +const fallbackfmt = {sb, params, tyenc, ap : valist# -> void + /* value types */ + var t_val : bool + var b_val : int8, ub_val : uint8 + var w_val : int16, uw_val : uint16 + var i_val : int32, ui_val : uint32 + var l_val : int64, ul_val : uint64 + var z_val : size + var p_val : byte# + var c_val : char + var s_val : byte[:] + var f32_val : flt32, f64_val : flt64 + var i8 : int8, i16: int16, i32 : int32 + var by : byte + var i : int, i64 : int64, l : long + var ui8 : int8, ui16: int16, ui32 : int32 + var ui : int, ui64 : int64, ul : long + + match typedesc(tyenc) + | `Tynone: /* nothing */ + /* atomic types */ + | `Tyvoid: + sbputs(sb, "void") + | `Tybool: + t_val = vanext(ap) + if t_val + sbputs(sb ,"true") + else + sbputs(sb, "false") + ;; + | `Tychar: + c_val = vanext(ap) + sbputc(sb, c_val) + | `Tyint8: + b_val = vanext(ap) + intfmt(sb, intparams(params), true, b_val) + | `Tyint16: + w_val = vanext(ap) + intfmt(sb, intparams(params), true, w_val) + | `Tyint: + i_val = vanext(ap) + intfmt(sb, intparams(params), true, i_val) + | `Tyint32: + i_val = vanext(ap) + intfmt(sb, intparams(params), true, i_val) + | `Tyint64: + l_val = vanext(ap) + intfmt(sb, intparams(params), true, l_val) + | `Tylong: + l_val = vanext(ap) + intfmt(sb, intparams(params), true, l_val) + + | `Tybyte: + ub_val = vanext(ap) + intfmt(sb, intparams(params), false, ub_val) + | `Tyuint8: + ub_val = vanext(ap) + intfmt(sb, intparams(params), false, ub_val) + | `Tyuint16: + uw_val = vanext(ap) + intfmt(sb, intparams(params), false, uw_val) + | `Tyuint: + ui_val = vanext(ap) + intfmt(sb, intparams(params), false, ui_val) + | `Tyuint32: + ui_val = vanext(ap) + intfmt(sb, intparams(params), false, ui_val) + | `Tyuint64: + ul_val = vanext(ap) + intfmt(sb, intparams(params), false, ul_val) + | `Tyulong: + ul_val = vanext(ap) + intfmt(sb, intparams(params), false, ul_val) + | `Tyflt32: + f32_val = vanext(ap) + flt32bfmt(sb, f32_val, MNormal, 0) + | `Tyflt64: + f64_val = vanext(ap) + flt64bfmt(sb, f64_val, MNormal, 0) + | `Tyvalist: + sbputs(sb, "...") + + /* compound types */ + | `Typtr desc: + p_val = vanext(ap) + sbputs(sb, "0x") + intfmt(sb, \ + [.base=16, .padto=2*sizeof(void#), .padfill='0'], \ + false, p_val castto(intptr)) + | `Tyslice desc: + match typedesc(desc) + | `Tybyte: + s_val = vanext(ap) + strfmt(sb, s_val, params) + | _: + sbputs(sb, "slice[:]") + ;; + | `Tyfunc tc: + p_val = vanext(ap) + sbputs(sb, "func{") + intfmt(sb, \ + [.base=16, .padto=2*sizeof(void#), .padfill='0'], \ + false, p_val castto(intptr)) + sbputs(sb, "}") + | `Tyarray (sz, data): + sbputs(sb, "array") + /* aggregate types */ + | `Tytuple typecursor: + vabytes(ap) + sbputs(sb, "tuple") + | `Tystruct namecursor: + vabytes(ap) + sbputs(sb, "struct") + | `Tyunion namecursor: + vabytes(ap) + sbputs(sb, "union") + | `Tyname (name, desc): + fallbackfmt(sb, params, desc, ap) + ;; +} + +const getparams = {fmt + var i + + for i = 0; i < fmt.len; i++ + if fmt[i] == '}' castto(byte) + goto foundparams + ;; + ;; + die("invalid format string") +:foundparams + -> (fmt[:i], fmt[i+1:]) +} + +type intparams = struct + base : size + padto : size + padfill : char +;; + +const intparams = {params + var ip : intparams + var opts + + ip = [ + .base = 10, + .padfill = ' ', + .padto = 0 + ] + + opts = parseparams(params, [ + ("x", false), + ("w", true), + ("p", true)][:]) + for o in opts + match o + | ("x", ""): ip.base = 16 + | ("w", wid): ip.padto = getint(wid, "fmt: width must be integer") + | ("p", pad): ip.padfill = decode(pad) + | _: std.die("unreachable") + ;; + ;; + std.assert(ip.padto >= 0, "pad must be >= 0") + std.slfree(opts) + -> ip +} + +const strfmt = {sb, str, params + var opts + var w, p, i + + p = ' ' + w = 0 + opts = parseparams(params, [ + ("w", true), + ("p", true)][:]) + for o in opts + match o + | ("w", wid): w = getint(wid, "fmt: width must be integer") + | ("p", pad): p = decode(pad) + | _: std.die("unreachable") + ;; + ;; + std.assert(p >= 0, "pad must be >= 0") + std.slfree(opts) + for i = 0; i < w - graphemewidth(str); i++ + sbputc(sb, p) + ;; + sbputs(sb, str) +} + +/* +Hah. like we're going to put in the work to actually +count graphemes. +*/ +const graphemewidth = {str + -> str.len +} + +const digitchars = [ + '0','1','2','3','4', + '5','6','7','8','9', + 'a','b','c','d','e','f' +] +generic intfmt = {sb, opts, signed, bits : @a::(integral,numeric) + var isneg + var val + var b : char[32] + var i, j, npad + var base + + base = opts.base castto(uint64) + if signed && bits < 0 + val = -bits castto(uint64) + isneg = true + else + val = bits castto(uint64) + val &= ~0 >> (8*(sizeof(uint64)-sizeof(@a))) + isneg = false + ;; + + i = 0 + if val == 0 + b[0] = '0' + i++ + ;; + while val != 0 + b[i] = digitchars[val % base] + val /= base + i++ + ;; + + npad = clamp(opts.padto - i, 0, opts.padto) + if isneg + npad-- + ;; + if opts.padfill == '0' && isneg + sbputc(sb, '-') + ;; + for j = 0; j < npad; j++ + sbputc(sb, opts.padfill) + ;; + if opts.padfill != '0' && isneg + sbputc(sb, '-') + ;; + for j = i; j != 0; j-- + sbputc(sb, b[j - 1]) + ;; +} + +const writeall = {fd, buf + var n, len + + len = 0 + while true + n = write(fd, buf) + if n <= 0 || n >= len + break + ;; + len += n + ;; + -> len +} + + +/* would use std.get(), but that's a dependency loop */ +const getint = {s, msg + match std.intparse(s) + | `Some w: -> w; + | `None: die(msg) + ;; +} diff --git a/lib/std/fmtfuncs.myr b/lib/std/fmtfuncs.myr new file mode 100644 index 0000000..abe5e75 --- /dev/null +++ b/lib/std/fmtfuncs.myr @@ -0,0 +1,54 @@ +use "alloc.use" +use "bigint.use" +use "bitset.use" +use "fmt.use" +use "introspect.use" +use "strbuf.use" +use "varargs.use" + +pkg std = +;; + +const __init__ = { + var bigint : bigint# + var bitset : bitset# + + fmtinstall(typeof(bigint), bigfmt, [][:]) + fmtinstall(typeof(bitset), bsfmt, [][:]) +} + +const bigfmt = {sb, ap, opts + var a, n, buf + + a = vanext(ap) + /* + allocate a buffer guaranteed to be big enough. + that's + 2 + floor(nbits/(log_2(10))) + or + 2 + a.dig.len * 32/3.32... + or + 2 + a.dig.len * 10 + plus one for the - sign. + */ + buf = slalloc(3 + a.dig.len * 10) + n = bigbfmt(buf, a, 10) + sbputs(sb, buf[:n]) + slfree(buf) +} + +const bsfmt = {sb, ap, opts + var i, bs, sep + + bs = vanext(ap) + sep = "" + sbputs(sb, "bitset{") + for i = 0; i < bsmax(bs); i++ + if bshas(bs, i) + sbfmt(sb, sep) + sbfmt(sb, "{}", i) + sep = ", " + ;; + ;; + sbputs(sb, "}") +} diff --git a/lib/std/getcwd.myr b/lib/std/getcwd.myr new file mode 100644 index 0000000..c9dbbea --- /dev/null +++ b/lib/std/getcwd.myr @@ -0,0 +1,31 @@ + +use "alloc.use" +use "errno.use" +use "extremum.use" +use "syswrap.use" +use "syswrap-ss.use" +pkg std = + const getcwd : (-> byte[:]) +;; + +const getcwd = { + var len, n, buf + + len = 128 + while true + buf = std.slalloc(len) + n = bgetcwd(buf) + if n >= 0 + /* n is the length of the nul terminated c string */ + -> buf[:n] + elif n != Erange + std.slfree(buf) + -> "" + else + len *= 2 + ;; + ;; + /* unreachable; shut up return without value analysis */ + -> "" +} + diff --git a/lib/std/getint.myr b/lib/std/getint.myr new file mode 100644 index 0000000..cd3d50b --- /dev/null +++ b/lib/std/getint.myr @@ -0,0 +1,64 @@ +pkg std = + generic getle64 : (buf : byte[:] -> @a::(numeric,integral)) + generic getbe64 : (buf : byte[:] -> @a::(numeric,integral)) + generic getle32 : (buf : byte[:] -> @a::(numeric,integral)) + generic getbe32 : (buf : byte[:] -> @a::(numeric,integral)) + generic getle16 : (buf : byte[:] -> @a::(numeric,integral)) + generic getbe16 : (buf : byte[:] -> @a::(numeric,integral)) + generic getle8 : (buf : byte[:] -> @a::(numeric,integral)) + generic getbe8 : (buf : byte[:] -> @a::(numeric,integral)) +;; + +generic getbe64 = {buf -> @a::(numeric,integral) + -> ((buf[0] castto(@a::(numeric,integral))) << 56) | \ + ((buf[1] castto(@a::(numeric,integral))) << 48) | \ + ((buf[2] castto(@a::(numeric,integral))) << 40) | \ + ((buf[3] castto(@a::(numeric,integral))) << 32) | \ + ((buf[4] castto(@a::(numeric,integral))) << 24) | \ + ((buf[5] castto(@a::(numeric,integral))) << 16) | \ + ((buf[6] castto(@a::(numeric,integral))) << 8) | \ + ((buf[7] castto(@a::(numeric,integral))) << 0) +} + +generic getle64 = {buf + -> ((buf[0] castto(@a::(numeric,integral))) << 0) | \ + ((buf[1] castto(@a::(numeric,integral))) << 8) | \ + ((buf[2] castto(@a::(numeric,integral))) << 16) | \ + ((buf[3] castto(@a::(numeric,integral))) << 24) | \ + ((buf[4] castto(@a::(numeric,integral))) << 32) | \ + ((buf[5] castto(@a::(numeric,integral))) << 40) | \ + ((buf[6] castto(@a::(numeric,integral))) << 48) | \ + ((buf[7] castto(@a::(numeric,integral))) << 56) +} + +generic getbe32 = {buf + -> ((buf[0] castto(@a::(numeric,integral))) << 24) | \ + ((buf[1] castto(@a::(numeric,integral))) << 16) | \ + ((buf[2] castto(@a::(numeric,integral))) << 8) | \ + ((buf[3] castto(@a::(numeric,integral))) << 0) +} + +generic getle32 = {buf + -> ((buf[0] castto(@a::(numeric,integral))) << 0) | \ + ((buf[1] castto(@a::(numeric,integral))) << 8) | \ + ((buf[2] castto(@a::(numeric,integral))) << 16) | \ + ((buf[3] castto(@a::(numeric,integral))) << 24) +} + +generic getbe16 = {buf + -> ((buf[0] castto(@a::(numeric,integral))) << 8) | \ + ((buf[1] castto(@a::(numeric,integral))) << 0) +} + +generic getle16 = {buf + -> ((buf[0] castto(@a::(numeric,integral))) << 0) | \ + ((buf[1] castto(@a::(numeric,integral))) << 8) +} + +generic getbe8 = {buf + -> (buf[0] castto(@a::(numeric,integral))) << 0 +} + +generic getle8 = {buf + -> (buf[0] castto(@a::(numeric,integral))) << 0 +} diff --git a/lib/std/hashfuncs.myr b/lib/std/hashfuncs.myr new file mode 100644 index 0000000..00c44c4 --- /dev/null +++ b/lib/std/hashfuncs.myr @@ -0,0 +1,106 @@ +use "die.use" +use "sleq.use" +use "types.use" + +pkg std = + const strhash : (s : byte[:] -> uint32) + const streq : (a : byte[:], b : byte[:] -> bool) + + generic ptrhash : (p : @a# -> uint32) + generic ptreq : (a : @a#, b : @a# -> bool) + + generic inthash : (v : @a::(integral,numeric) -> uint32) + generic inteq : (a : @a::(integral,numeric), b : @a::(integral,numeric) -> bool) + + const murmurhash2 : (data : byte[:], seed : uint32 -> uint32) + + generic slhash : (sl : @a[:] -> uint32) + generic tobytes : (sl : @a[:] -> byte[:]) +;; + +const Seed = 1234 + +generic slhash = {data : @a[:] + -> strhash(slbytes(data)) +} + +generic slbytes = {data : @a[:] + var n + + n = data.len * sizeof(@a) + -> (data castto(byte#))[:n] +} + +/* Supremely simple djb hash. */ +const strhash = {s + -> murmurhash2(s, Seed) +} + +const streq = {a, b + -> sleq(a, b) +} + +generic ptrhash = {p : @a# + var x + + x = &p castto(byte#) + -> murmurhash2(x[0:sizeof(@a)], Seed) +} + +generic ptreq = {a, b + -> a == b +} + +generic inthash = {v : @a::(integral,numeric) + var p + + p = &v castto(byte#) + -> murmurhash2(p[0:sizeof(@a)], Seed) +} + +generic inteq = {a, b + -> a == b +} + +const murmurhash2 = {data, seed + const m = 0x5bd1e995; + const r = 24 + var h, k + + h = seed ^ data.len + while data.len >= 4 + k = (data[0] castto(uint32)) + k |= (data[1] castto(uint32)) << 8 + k |= (data[2] castto(uint32)) << 16 + k |= (data[3] castto(uint32)) << 24 + + k *= m + k ^= k >> r + k *= m + + h *= m + h ^= k + data = data[4:] + ;; + + match data.len + | 3: + h ^= (data[2] castto(uint32)) << 16 + h ^= (data[1] castto(uint32)) <<8 + h ^= (data[0] castto(uint32)) + | 2: + h ^= (data[1] castto(uint32)) <<8 + h ^= (data[0] castto(uint32)) + | 1: + h ^= (data[0] castto(uint32)) + | 0: /* nothing */ + | _: die("0 < len < 4 must be true") + ;; + h *= m + + h ^= h >> 13 + h *= m + h ^= h >> 15 + + -> h +} diff --git a/lib/std/hasprefix.myr b/lib/std/hasprefix.myr new file mode 100644 index 0000000..c9749f6 --- /dev/null +++ b/lib/std/hasprefix.myr @@ -0,0 +1,12 @@ +use "cmp.use" +pkg std = + const hasprefix : (s : byte[:], pre : byte[:] -> bool) +;; + +const hasprefix = {s, pre + match strncmp(s, pre, pre.len) + | `Equal: -> true + | _: -> false + ;; +} + diff --git a/lib/std/hassuffix.myr b/lib/std/hassuffix.myr new file mode 100644 index 0000000..87369af --- /dev/null +++ b/lib/std/hassuffix.myr @@ -0,0 +1,15 @@ +use "sleq.use" +pkg std = + const hassuffix : (s : byte[:], suff : byte[:] -> bool) +;; + +const hassuffix = {s, suff + var tail + + if suff.len <= s.len + tail = s[s.len - suff.len:] + -> sleq(tail, suff) + ;; + -> false +} + diff --git a/lib/std/htab.myr b/lib/std/htab.myr new file mode 100644 index 0000000..ac2e7aa --- /dev/null +++ b/lib/std/htab.myr @@ -0,0 +1,209 @@ +use "alloc.use" +use "die.use" +use "extremum.use" +use "option.use" +use "types.use" + +pkg std = + type htab(@k, @v) = struct + hash : (k : @k -> uint32) + eq : (a : @k, b : @k -> bool) + + nelt : size + ndead : size + keys : @k[:] + vals : @v[:] + hashes : uint32[:] + dead : bool[:] + ;; + + generic mkht : (h : (k : @k -> uint32), eq : (a : @k, b : @k -> bool) -> htab(@k, @v)#) + generic htfree : (ht : htab(@k, @v)# -> void) + generic htput : (ht : htab(@k, @v)#, k : @k, v : @v -> void) + generic htdel : (ht : htab(@k, @v)#, k : @k -> void) + generic htget : (ht : htab(@k, @v)#, k : @k -> option(@v)) + generic htgetv : (ht : htab(@k, @v)#, k : @k, fallback : @v-> @v) + generic hthas : (ht : htab(@k, @v)#, k : @k -> bool) + generic htkeys : (ht : htab(@k, @v)# -> @k[:]) +;; + +const Initsz = 32 + +extern const put : (fmt : byte[:], args : ... -> size) + +generic hash = {ht, k + var h + + h = ht.hash(k) + if h == 0 + -> 1 + else + -> h + ;; +} + +generic resize = {ht, sz + var oldk + var oldv + var oldh + var oldd + var i + + oldk = ht.keys + oldv = ht.vals + oldh = ht.hashes + oldd = ht.dead + ht.keys = slalloc(sz) + ht.vals = slalloc(sz) + ht.hashes = slzalloc(sz) + ht.dead = slzalloc(sz) + + ht.nelt = 0 + ht.ndead = 0 + for i = 0; i < oldk.len; i++ + if oldh[i] != 0 && !oldd[i] + htput(ht, oldk[i], oldv[i]) + ;; + ;; + slfree(oldk) + slfree(oldv) + slfree(oldh) + slfree(oldd) +} + +generic idx = {ht, k + var i, di + var h + + di = 0 + h = hash(ht, k) + i = h & (ht.keys.len - 1) + while true + while ht.hashes[i] != 0 && !ht.dead[i] && ht.hashes[i] != h + di++ + i = (h + di) & (ht.keys.len - 1) + ;; + + if ht.hashes[i] == 0 + -> `None + ;; + if ht.hashes[i] == h && !ht.dead[i] && ht.eq(ht.keys[i], k) + break + ;; + di++ + i = (h + di) & (ht.keys.len - 1) + ;; + -> `Some i +} + +generic mkht = {h, eq + var ht + + ht = alloc() + + ht.hash = h + ht.eq = eq + + ht.nelt = 0 + ht.ndead = 0 + ht.keys = slalloc(Initsz) + ht.vals = slalloc(Initsz) + ht.hashes = slzalloc(Initsz) + ht.dead = slzalloc(Initsz) + -> ht +} + +generic htfree = {ht + slfree(ht.keys) + slfree(ht.vals) + slfree(ht.hashes) + slfree(ht.dead) + free(ht) +} + +generic htput = {ht, k, v + var i, di + var h + var neltincr + + di = 0 + h = hash(ht, k) + i = h & (ht.keys.len - 1) + neltincr = 1 + while ht.hashes[i] != 0 && !ht.dead[i] + /* second insertion overwrites */ + if ht.hashes[i] == h && !ht.dead[i] + /* dead key, we can just insert here */ + if ht.dead[i] + break + /* replacing a key */ + elif ht.eq(ht.keys[i], k) + neltincr = 0 + break + ;; + ;; + di++ + i = (h + di) & (ht.keys.len - 1) + ;; + ht.nelt += neltincr + ht.hashes[i] = h + ht.keys[i] = k + ht.vals[i] = v + ht.dead[i] = false + if ht.keys.len < ht.nelt * 2 + resize(ht, 2*ht.keys.len) + ;; +} + +generic htdel = {ht, k + match idx(ht, k) + | `Some i: + ht.dead[i] = true + ht.nelt-- + ht.ndead++ + std.put("ndead = {}\n", ht.ndead) + /* remove tombstones if we shrink enough */ + if ht.keys.len < ht.ndead * 4 + resize(ht, ht.keys.len) + ;; + | _: + /* do nothing */ + ;; +} + +generic htget = {ht, k + match idx(ht, k) + | `Some i: -> `Some ht.vals[i] + | `None: -> `None + ;; +} + +generic htgetv = {ht, k, v + match idx(ht, k) + | `Some i: -> ht.vals[i] + | `None: -> v + ;; +} + +generic hthas = {ht, k + match idx(ht, k) + | `Some i: -> true + | `None: -> false + ;; +} + +generic htkeys = {ht + var keys + var i + var j + + keys = slalloc(ht.nelt) + j = 0 + for i = 0; i < ht.keys.len; i++ + if ht.hashes[i] != 0 && !ht.dead[i] + keys[j++] = ht.keys[i] + ;; + ;; + -> keys +} + diff --git a/lib/std/ifreq+freebsd.myr b/lib/std/ifreq+freebsd.myr new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/std/ifreq+freebsd.myr diff --git a/lib/std/ifreq+linux.myr b/lib/std/ifreq+linux.myr new file mode 100644 index 0000000..62be8ee --- /dev/null +++ b/lib/std/ifreq+linux.myr @@ -0,0 +1,67 @@ +use "sys.use" + +pkg sys = + const Ifnamesz = 16 + + type ifreq_addr = struct + name : byte[Ifnamesz] + addr : sockaddr + ;; + + type ifreq_dstaddr = struct + name : byte[Ifnamesz] + dstaddr : sockaddr + ;; + + type ifreq_broadaddr = struct + name : byte[Ifnamesz] + broadaddr : sockaddr + ;; + + type ifreq_netmask = struct + name : byte[Ifnamesz] + netmask : sockaddr + ;; + + + type ifreq_hwaddr = struct + name : byte[Ifnamesz] + hwaddr : sockaddr + ;; + + type ifreq_flags = struct + name : byte[Ifnamesz] + flags : int16 + ;; + + type ifreq_ifindex = struct + name : byte[Ifnamesz] + index : int32 + ;; + + type ifreq_metric = struct + name : byte[Ifnamesz] + metric : int32 + ;; + + + type ifreq_mtu = struct + name : byte[Ifnamesz] + mtu : int32 + ;; + + type ifreq_slave = struct + name : byte[Ifnamesz] + slave : byte[Ifnamesz] + ;; + + type ifreq_newname = struct + name : byte[Ifnamesz] + newname : byte[Ifnamesz] + ;; + + type ifreq_data = struct + name : byte[Ifnamesz] + data : void# + ;; +;; diff --git a/lib/std/ifreq+osx.myr b/lib/std/ifreq+osx.myr new file mode 100644 index 0000000..f5205bf --- /dev/null +++ b/lib/std/ifreq+osx.myr @@ -0,0 +1,77 @@ +use "sys.use" + +pkg sys = + const Ifnamesz = 16 + + type ifreq_addr = struct + name : byte[Ifnamesz] + addr : sockaddr + ;; + + type ifreq_dstaddr = struct + name : byte[Ifnamesz] + dstaddr : sockaddr + ;; + + type ifreq_broadaddr = struct + name : byte[Ifnamesz] + broadaddr : sockaddr + ;; + + type ifreq_flags = struct + name : byte[Ifnamesz] + flags : int16 + ;; + + type ifreq_metric = struct + name : byte[Ifnamesz] + metric : int32 + ;; + + + type ifreq_phys = struct + name : byte[Ifnamesz] + phys : int32 + ;; + + type ifreq_media = struct + name : byte[Ifnamesz] + media : int32 + ;; + + type ifreq_data = struct + name : byte[Ifnamesz] + data : void# + ;; + + type ifreq_devmtu = struct + name : byte[Ifnamesz] + cur : uint32 + min : uint32 + max : uint32 + ;; + + type ifreq_kpi = struct + name : byte[Ifnamesz] + modid : uint32 + typeid : uint32 + ptr : void# + ;; + + type ifreq_wakeflg = struct + name : byte[Ifnamesz] + wakeflg : uint32 + ;; + + type ifreq_routerefs = struct + name : byte[Ifnamesz] + refs : uint32 + ;; + + type ifreq_icaps = struct + name : byte[Ifnamesz] + req : uint32 + cur : uint32 + ;; + +;; diff --git a/lib/std/ifreq+plan9.myr b/lib/std/ifreq+plan9.myr new file mode 100644 index 0000000..ef73843 --- /dev/null +++ b/lib/std/ifreq+plan9.myr @@ -0,0 +1,2 @@ +pkg std = +;; diff --git a/lib/std/intparse.myr b/lib/std/intparse.myr new file mode 100644 index 0000000..4180f8c --- /dev/null +++ b/lib/std/intparse.myr @@ -0,0 +1,70 @@ +use "chartype.use" +use "die.use" +use "hasprefix.use" +use "option.use" +use "types.use" +use "utf.use" + +pkg std = + generic intparsebase : (s : byte[:], base : int -> option(@a::(integral,numeric))) + generic intparse : (s : byte[:] -> option(@a::(integral,numeric))) +;; + +generic intparse = {s + var isneg + + isneg = false + if hasprefix(s, "-") + s = s[1:] + isneg = true + ;; + + if hasprefix(s, "0x") + -> doparse(s[2:], isneg, 16) + elif hasprefix(s, "0o") + -> doparse(s[2:], isneg, 8) + elif hasprefix(s, "0b") + -> doparse(s[2:], isneg, 2) + else + -> doparse(s, isneg, 10) + ;; +} + +generic intparsebase = {s, base + var isneg + + isneg = false + if hasprefix(s, "-") + s = s[1:] + isneg = true + ;; + + -> doparse(s, isneg, base) +} + +generic doparse = {s, isneg, base + var c + var v + var cv : int32 + + v = 0 + while s.len != 0 + (c, s) = striter(s) + if c == '_' + continue + ;; + cv = charval(c, base) + if cv >= 0 + v *= (base castto(@a::(integral,numeric))) + v += cv castto(@a::(integral,numeric)) + else + -> `None + ;; + ;; + + if isneg + -> `Some -v + else + -> `Some v + ;; +} diff --git a/lib/std/introspect.myr b/lib/std/introspect.myr new file mode 100644 index 0000000..1da7af0 --- /dev/null +++ b/lib/std/introspect.myr @@ -0,0 +1,365 @@ +use "types.use" +use "die.use" + +pkg std = + type typedesc = union + `Tynone + + /* atomic types */ + `Tyvoid + `Tybool + `Tychar + + `Tyint8 + `Tyint16 + `Tyint + `Tyint32 + `Tyint64 + `Tylong + + `Tybyte + `Tyuint8 + `Tyuint16 + `Tyuint + `Tyuint32 + `Tyuint64 + `Tyulong + `Tyflt32 + `Tyflt64 + `Tyvalist + + /* compound types */ + `Typtr byte[:] + `Tyfunc typecursor + `Tyslice byte[:] + `Tyarray (size, byte[:]) + + /* aggregate types */ + `Tytuple typecursor + `Tystruct namecursor + `Tyunion namecursor + /* name info */ + `Tyname (byte[:], byte[:]) + ;; + + type typecursor = struct + nelt : size + rem : byte[:] + ;; + + type namecursor = struct + nelt : size + rem : byte[:] + ;; + + type typeinfo = struct + size : size + align : size + ;; + + generic typeof : (v : @a -> byte[:]) + const typeenc : (p : ...# -> typecursor) + const typedecode : (e : byte[:] -> typedesc) + const typedesc : (e : byte[:] -> typedesc) + const typeinfo : (e : byte[:] -> typeinfo) + + const tcnext : (t : typecursor# -> byte[:]) + const tcpeek : (t : typecursor# -> byte[:]) + const ncnext : (t : namecursor# -> (byte[:], byte[:])) +;; + +extern const put : (fmt : byte[:], args : ... -> size) + +const Encnone : byte = 0 +const Encvoid : byte = 1 +const Encbool : byte = 2 +const Encchar : byte = 3 + +const Encint8 : byte = 4 +const Encint16 : byte = 5 +const Encint : byte = 6 +const Encint32 : byte = 7 +const Encint64 : byte = 8 +const Enclong : byte = 9 + +const Encbyte : byte = 10 +const Encuint8 : byte = 11 +const Encuint16 : byte = 12 +const Encuint : byte = 13 +const Encuint32 : byte = 14 +const Encuint64 : byte = 15 +const Enculong : byte = 16 +const Encflt32 : byte = 17 +const Encflt64 : byte = 18 +const Encvalist : byte = 19 + +/* compound types */ +const Encptr : byte = 20 +const Encfunc : byte = 21 +const Encslice : byte = 22 +const Encarray : byte = 23 + +/* aggregate types */ +const Enctuple : byte = 24 +const Encstruct : byte = 25 +const Encunion : byte = 26 +const Encname : byte = 30 +const Encindname :byte = 30 | 0x80 + +generic typeof = {v : @a -> byte[:] + var tc + + tc = typesof(v) + -> tcnext(&tc) +} + +const typeenc = {ap : ...# + var e + + e = getenc(ap castto(byte##)) + e = skiptypeinfo(e[1:]) + -> lentypecursor(e) +} + +const typesof : (a : ... -> typecursor) = {a : ... + -> typeenc(&a) +} + +const tcnext = {tc + var n, sz, cur + + if tc.rem.len == 0 + -> "" + ;; + (n, sz) = getipacked(tc.rem) + cur = tc.rem[sz:sz+n] + tc.rem = tc.rem[sz+n:] + -> cur +} + +const tcpeek = {tc + var n, sz + + if tc.rem.len == 0 + -> "" + ;; + (n, sz) = getipacked(tc.rem) + -> tc.rem[sz:sz+n] +} + +const ncnext = {nc + var n, sz, name, enc + + if nc.rem.len == 0 + -> ("", "") + ;; + + /* get the name */ + (n, sz) = getipacked(nc.rem) + name = nc.rem[sz:sz+n] + nc.rem = nc.rem[sz+n:] + + /* and the type */ + (n, sz) = getipacked(nc.rem) + enc = nc.rem[sz:sz+n] + nc.rem = nc.rem[sz+n:] + -> (name, enc) +} + + +const getenc = {p : byte## + var val, sz, x + + (val, sz) = getipacked(p#[:8]) + x = &sz castto(byte#) + -> p#[sz:sz+val] +} + +const typedesc = {ti + var len,sz, p + + match ti[0] + | Encnone: -> `Tynone + | Encvoid: -> `Tyvoid + | Encbool: -> `Tybool + | Encchar: -> `Tychar + + | Encint8: -> `Tyint8 + | Encint16: -> `Tyint16 + | Encint: -> `Tyint + | Encint32: -> `Tyint32 + | Encint64: -> `Tyint64 + | Enclong: -> `Tylong + + | Encbyte: -> `Tybyte + | Encuint8: -> `Tyuint8 + | Encuint16: -> `Tyuint16 + | Encuint: -> `Tyuint + | Encuint32: -> `Tyuint32 + | Encuint64: -> `Tyuint64 + | Enculong: -> `Tyulong + | Encflt32: -> `Tyflt32 + | Encflt64: -> `Tyflt64 + | Encvalist: -> `Tyvalist + + /* compound types */ + | Encptr: -> `Typtr getsub(ti[1:]) + | Encfunc: -> `Tyfunc lentypecursor(ti[1:]) + | Encslice: -> `Tyslice getsub(ti[1:]) + | Encarray: + ti = skiptypeinfo(ti[1:]) + (len, sz) = getipacked(ti) + -> `Tyarray (len, getsub(ti[sz:])) + + + /* aggregate types */ + | Enctuple: + ti = skiptypeinfo(ti[1:]) + -> `Tytuple lentypecursor(ti) + | Encstruct: + ti = skiptypeinfo(ti[1:]) + -> `Tystruct lennamecursor(ti) + | Encunion: + ti = skiptypeinfo(ti[1:]) + -> `Tyunion lennamecursor(ti) + | Encname: + -> `Tyname namedesc(ti[1:]) + | Encindname: + /* + ugly hack: the slice contains a pointer to the + value, so if we cast it to a byte##, we can + pull the indirect value out of the pointer. + */ + p = ti[1:] castto(byte##) + -> typedesc(getenc(p)) + | _: + std.die("unknown type encoding") + ;; +} + +const typeinfo = {ti + var p + + match ti[0] + | Encnone: -> [.size=0, .align=1] + | Encvoid: -> [.size=0, .align=1] + | Encbool: -> [.size=0, .align=1] + | Encchar: -> [.size=4, .align=4] + + | Encint8: -> [.size=1, .align=1] + | Encint16: -> [.size=2, .align=2] + | Encint: -> [.size=4, .align=4] + | Encint32: -> [.size=4, .align=4] + | Encint64: -> [.size=8, .align=8] + | Enclong: -> [.size=8, .align=8] + + | Encbyte: -> [.size=1, .align=1] + | Encuint8: -> [.size=1, .align=1] + | Encuint16: -> [.size=2, .align=2] + | Encuint: -> [.size=4, .align=4] + | Encuint32: -> [.size=4, .align=4] + | Encuint64: -> [.size=8, .align=8] + | Enculong: -> [.size=8, .align=8] + | Encflt32: -> [.size=4, .align=4] + | Encflt64: -> [.size=8, .align=8] + | Encvalist: -> [.size=8, .align=8] + + /* compound types */ + | Encptr: -> [.size=8, .align=8] + | Encfunc: -> [.size=8, .align=8] + | Encslice: -> [.size=16, .align=8] + + | Encarray: -> gettypeinfo(ti[1:]) + | Enctuple: -> gettypeinfo(ti[1:]) + | Encstruct: -> gettypeinfo(ti[1:]) + | Encunion: -> gettypeinfo(ti[1:]) + | Encname: -> getnameinfo(ti[1:]) + | Encindname: + p = ti[1:] castto(byte##) + -> typeinfo(getenc(p)) + | _: + std.die("unknown type encoding") + ;; +} + +const gettypeinfo = {e + var size, align, sz + + (size, sz) = getipacked(e) /* size */ + e = e[sz:] + (align, sz) = getipacked(e) /* align */ + -> [.size = size, .align = align] +} + +const skiptypeinfo = {e + var ignore, sz + + (ignore, sz) = getipacked(e) /* size */ + e = e[sz:] + (ignore, sz) = getipacked(e) /* align */ + -> e[sz:] +} + +const getnameinfo = {e + var n, name, sz, enc + + (n, sz) = getipacked(e) + name = e[sz:n+sz] + e = e[n+sz:] + (n, sz) = getipacked(e) + enc = e[sz:n+sz] + + -> typeinfo(enc) +} + +const namedesc = {e + var n, sz, name, enc + + (n, sz) = getipacked(e) + name = e[sz:n+sz] + e = e[n+sz:] + (n, sz) = getipacked(e) + enc = e[sz:n+sz] + + -> (name, enc) +} + +const lentypecursor = {e + var n, sz + + (n, sz) = getipacked(e) + -> [.nelt=n, .rem=e[sz:]] +} + +const lennamecursor = {e + var n, sz + + (n, sz) = getipacked(e) + -> [.nelt=n, .rem=e[sz:]] +} + +const getsub = {e + var n, sz + + (n, sz) = getipacked(e) + -> e[sz:sz+n] +} + +const getipacked : (p : byte[:] -> (size, size)) = {p : byte[:] + var mask, val, len, i + + mask = 0x80 + val = 0 + len = 1 + while p[0] & mask != mask << 1 + len++ + mask >>= 1 + mask |= 0x80 + ;; + + val = (p[0] castto(size)) & ~(1 << (8 - len)) + for i = 1; i < len; i++ + val |= (p[i] castto(size)) << (i*8 - len) + ;; + -> (val, len) +} diff --git a/lib/std/ipparse.myr b/lib/std/ipparse.myr new file mode 100644 index 0000000..17bc6f0 --- /dev/null +++ b/lib/std/ipparse.myr @@ -0,0 +1,147 @@ +use "die.use" +use "intparse.use" +use "option.use" +use "strfind.use" +use "types.use" +use "chartype.use" +use "fmt.use" +use "slcp.use" +use "slfill.use" +use "sleq.use" + + /* FIXME: needed for decls which should be pulled in as hidden */ +use "hasprefix.use" +use "utf.use" + +pkg std = + + type netaddr = union + `Ipv4 byte[4] + `Ipv6 byte[16] + ;; + + const ipparse : (ip : byte[:] -> option(netaddr)) + const ip4parse : (ip : byte[:] -> option(netaddr)) + const ip6parse : (ip : byte[:] -> option(netaddr)) +;; + +const ipparse = {ip + match strfind(ip, ":") + | `Some _: -> ip6parse(ip) + | `None: -> ip4parse(ip) + ;; +} + +const ip4parse = {ip + var a, b, c, d + var ok + /* + var addr + var last : size + var x : option(int32) + var val : int32 /* need int32 to check for overflow */ + var i + var j : size + */ + + (a, ip, ok) = num(ip, 0, 255, 10, '.', true) + (ip, ok) = delim(ip, '.', ok) + (b, ip, ok) = num(ip, 0, 255, 10, '.', ok) + (ip, ok) = delim(ip, '.', ok) + (c, ip, ok) = num(ip, 0, 255, 10, '.', ok) + (ip, ok) = delim(ip, '.', ok) + (d, ip, ok) = num(ip, 0, 255, 10, '.', ok) + + if ok && ip.len == 0 + -> `Some (`Ipv4 [a, b, c, d]) + else + -> `None + ;; +} + +const ip6parse = {ip + var val : byte[16] + var expand, split + var v, ok + var i, nseg + + ok = true + expand = false + split = 0 + if ip.len > 2 && std.sleq(ip[:2], "::") + expand = true + split = 0 + ;; + nseg = 0 + for i = 0; ip.len > 0 && ok; i++ + /* parse 'num' segment */ + (v, ip, ok) = num(ip, 0, 65536, 16, ':', ok) + nseg++ + if ip.len == 0 || nseg == 8 + break + ;; + (ip, ok) = delim(ip, ':', ok) + /* only one '::' allowed once */ + if ip.len > 0 && ip[0] == ':'castto(byte) && !expand + expand = true + split = i + (ip, ok) = delim(ip, ':', ok) + ;; + + /* pack it into the bytes */ + val[i*2] = ((v & 0xff00) >> 8) castto(byte) + val[i*2 + 1] = (v & 0xff) castto(byte) + ;; + + if ok && ip.len == 0 + if expand + expandsplit(val[:], split, i) + elif nseg != 8 + -> `None + ;; + -> `Some `Ipv6 val + else + -> `None + ;; +} + +/* take "a:b::c:d" and expand it to "a:b:0:0:...:0:c:d" */ +const expandsplit = {ip, split, len + var width + + width = 16 - len + std.slcp(ip[split:len], ip[split+width:len+width]) + std.slfill(ip[len:len+width], 0) +} + +const delim = {ip, sep, ok + if ip.len > 0 && ip[0] == sep castto(byte) + -> (ip[1:], ok) + else + -> ("", false) + ;; +} + +generic num = {ip, lo, hi, base, sep, ok -> (@a::(numeric,integral), byte[:], bool) + var len + + if !ok + -> (0, "", false) + ;; + + for len = 0; len < ip.len; len++ + if ip[len] == sep castto(byte) + break + ;; + ;; + match intparsebase(ip[:len], base) + | `std.Some v: + if v < lo || v > hi + -> (0, "", false) + ;; + -> (v castto(@a::(numeric,integral)), ip[len:], true) + | `std.None: + -> (0, "", false) + ;; +} + diff --git a/lib/std/mk.myr b/lib/std/mk.myr new file mode 100644 index 0000000..19b46d2 --- /dev/null +++ b/lib/std/mk.myr @@ -0,0 +1,22 @@ +use "alloc.use" + +pkg std = + generic mk : (val : @a -> @a#) +;; + +/* Takes a value, and heapifies it. + +FIXME: This depends on inlining and copy propagation +in order to be efficient. Neither of those are +currently implemented. That means that this function +is not efficient. + +It's still damn convenient, though, so it's in. +*/ +generic mk = {val + var p + + p = alloc() + p# = val + -> p +} diff --git a/lib/std/mkfile b/lib/std/mkfile new file mode 100644 index 0000000..36c6bb2 --- /dev/null +++ b/lib/std/mkfile @@ -0,0 +1,107 @@ +</$objtype/mkfile + +SYSLIB=sys +SYSSRC= \ + sys.myr \ + systypes.myr \ + ifreq.myr \ + +SYSASMSRC= \ + syscall.s \ + util.s + + +STDLIB=std +STDSRC= \ + alloc.myr \ + bigint.myr \ + bitset.myr \ + blat.myr \ + chartype.myr \ + cmp.myr \ + dial.myr \ + die.myr \ + dir.myr \ + endian.myr \ + env.myr \ + execvp.myr \ + extremum.myr \ + fltbits.myr \ + fmt.myr \ + fltfmt.myr \ + hashfuncs.myr \ + hasprefix.myr \ + hassuffix.myr \ + htab.myr \ + intparse.myr \ + ipparse.myr \ + mk.myr \ + now.myr \ + option.myr \ + optparse.myr \ + pathjoin.myr \ + rand.myr \ + resolve.myr \ + result.myr \ + search.myr \ + slcp.myr \ + sldup.myr \ + sleq.myr \ + slfill.myr \ + sljoin.myr \ + slpush.myr \ + slput.myr \ + slurp.myr \ + sort.myr \ + spork.myr \ + strfind.myr \ + strjoin.myr \ + strsplit.myr \ + strstrip.myr \ + syswrap.myr \ + swap.myr \ + try.myr \ + types.myr \ + units.myr \ + utf.myr \ + varargs.myr \ + wait.myr \ + +all:V: lib$STDLIB.a lib$SYSLIB.a + +install:V: all + mkdir -p /$objtype/lib/myr/ + cp lib$STDLIB.a lib$SYSLIB.a /$objtype/lib/myr/ + cp $STDLIB $SYSLIB /$objtype/lib/myr/ + +lib$STDLIB.a: $STDSRC $ASMSRC lib$SYSLIB.a + ../myrbuild/$O.out -I. -C../6/$O.out -M../muse/$O.out -l $STDLIB $STDSRC $STDASMSRC + +lib$SYSLIB.a: $SYSSRC $SYSASMSRC + ../myrbuild/$O.out -C../6/$O.out -M../muse/$O.out -l $SYSLIB $SYSSRC $SYSASMSRC + +%.myr: %+plan9-x64.myr + cp $stem+plan9-x64.myr $stem.myr + +%.myr: %+plan9.myr + cp $stem+plan9.myr $stem.myr + +%.myr: %+x64.myr + cp $stem+x64.myr $stem.myr + +%.s: %+plan9-x64.s + cp $stem+plan9-x64.s $stem.s + +%.s: %+x64.s + cp $stem+x64.s $stem.s + +OBJ=${STDSRC:%.myr=%.$O} ${SYSSRC:%.myr=%.$O} ${STDASMSRC:%.s=%.$O} ${SYSASMSRC:%.s=%.$O} +USE=${STDSRC:%.myr=%.use} ${SYSSRC:%.myr=%.use} ${STDLIB} +LIBS=lib$STDLIB.a lib$SYSLIB.a +.PHONY: clean +clean:V: + rm -f $OBJ + rm -f $USE + rm -f $LIBS $STDLIB $SYSLIB + +nuke:V: clean diff --git a/lib/std/mkpath.myr b/lib/std/mkpath.myr new file mode 100644 index 0000000..b7e8e24 --- /dev/null +++ b/lib/std/mkpath.myr @@ -0,0 +1,22 @@ +use "syswrap.use" +use "errno.use" + +pkg std = + const mkpath : (p : byte[:] -> bool) +;; + +const mkpath = {p + var st + var i + + for i = 0; i < p.len; i++ + if p[i] == '/' castto(byte) && i != 0 + st = mkdir(p[:i], 0o777) + if st != 0 && (st castto(errno)) != Eexist + -> false + ;; + ;; + ;; + + -> true +} diff --git a/lib/std/now.myr b/lib/std/now.myr new file mode 100644 index 0000000..5f6d8d1 --- /dev/null +++ b/lib/std/now.myr @@ -0,0 +1,11 @@ +use "types.use" +use "syswrap.use" + +pkg std = + const now : (-> time) +;; + +/* microseconds since epoch */ +const now = { + -> curtime() +} diff --git a/lib/std/option.myr b/lib/std/option.myr new file mode 100644 index 0000000..271355d --- /dev/null +++ b/lib/std/option.myr @@ -0,0 +1,7 @@ +pkg std = + type option(@a) = union + `Some @a + `None + ;; +;; + diff --git a/lib/std/optparse.myr b/lib/std/optparse.myr new file mode 100644 index 0000000..ae65b77 --- /dev/null +++ b/lib/std/optparse.myr @@ -0,0 +1,210 @@ +use "alloc.use" +use "die.use" +use "extremum.use" +use "fmt.use" +use "strbuf.use" +use "option.use" +use "sleq.use" +use "slpush.use" +use "syswrap-ss.use" +use "syswrap.use" +use "types.use" +use "utf.use" + +pkg std = + type optdef = struct + argdesc : byte[:] /* the description for the usage */ + minargs : std.size /* the minimum number of positional args */ + maxargs : std.size /* the maximum number of positional args (0 = unlimited) */ + noargs : std.bool /* whether we accept args at all */ + opts : optdesc[:] /* the description of the options */ + ;; + + type optdesc = struct + opt : char + arg : byte[:] + desc : byte[:] + optional : bool + ;; + + type optparsed = struct + opts : (char, byte[:])[:] + args : byte[:][:] + ;; + + const optparse : (optargs : byte[:][:], def : optdef# -> optparsed) + const optusage : (prog : byte[:], def : optdef# -> void) +;; + +type optctx = struct + /* public variables */ + args : byte[:][:] + + /* data passed in */ + optdef : optdef# + optargs : byte[:][:] + + /* state */ + argidx : size + curarg : byte[:] + optdone : bool /* if we've seen '--', everything's an arg */ + finished : bool /* if we've processed all the optargs */ +;; + + +const optparse = {args, def + var ctx : optctx + var parsed + + parsed = [ + .opts=[][:], + .args=[][:] + ] + optinit(&ctx, args, def) + while !optdone(&ctx) + parsed.opts = slpush(parsed.opts, optnext(&ctx)) + ;; + if ctx.args.len < def.minargs + put("error: expected at least {} args, got {}\n", def.minargs, ctx.args.len) + optusage(ctx.optargs[0], ctx.optdef) + exit(1) + ;; + if def.maxargs > 0 && ctx.args.len < def.minargs + put("error: expected at most {} args, got {}\n", def.minargs, ctx.args.len) + optusage(ctx.optargs[0], ctx.optdef) + exit(1) + ;; + if def.noargs && ctx.args.len != 0 + put("error: expected no args, got {}\n", ctx.args.len) + optusage(ctx.optargs[0], ctx.optdef) + exit(1) + ;; + parsed.args = ctx.args + -> parsed +} + +const optinit = {ctx, args, def + ctx# = [ + .optargs = args, + .optdef = def, + .optdone = false, + .finished = false, + .argidx = 0, + .curarg = [][:], + .args = [][:], + ] + + next(ctx) + -> ctx +} + +const optnext = {ctx + var c + var arg + + (c, ctx.curarg) = striter(ctx.curarg) + + match optinfo(ctx, c) + | `None: + if c == 'h' || c == '?' + optusage(ctx.optargs[0], ctx.optdef) + exit(0) + else + fatal("unexpected argument '{}'\n", c) + ;; + | `Some (true, needed): + /* -arg => '-a' 'rg' */ + if ctx.curarg.len > 0 + arg = ctx.curarg + ctx.curarg = ctx.curarg[ctx.curarg.len:] + next(ctx) + /* '-a rg' => '-a' 'rg' */ + elif ctx.argidx < (ctx.optargs.len - 1) + arg = ctx.optargs[ctx.argidx + 1] + ctx.argidx++ + next(ctx) + elif needed + put("Expected argument for {}\n", c) + exit(1) + ;; + | `Some (false, _): + arg = "" + if ctx.curarg.len == 0 + next(ctx) + ;; + ;; + + + -> (c, arg) +} + +const optdone = {ctx + -> ctx.curarg.len == 0 && ctx.finished +} + +const optinfo = {ctx, opt + for o in ctx.optdef.opts + if o.opt == opt + -> `Some (o.arg.len != 0, !o.optional) + ;; + ;; + -> `None +} + +const next = {ctx + var i + + for i = ctx.argidx + 1; i < ctx.optargs.len; i++ + if !ctx.optdone && decode(ctx.optargs[i]) == '-' + if sleq(ctx.optargs[i], "--") + ctx.optdone = true + else + goto foundopt + ;; + else + ctx.args = slpush(ctx.args, ctx.optargs[i]) + ;; + ;; +:finishedopt + ctx.finished = true + -> false +:foundopt + ctx.argidx = i + ctx.curarg = ctx.optargs[i][1:] + -> true +} + +const optusage = {prog, def + var sb, s + + sb = mksb() + std.sbfmt(sb, "usage: {} [-h?", prog) + for o in def.opts + if o.arg.len == 0 + std.sbfmt(sb, "{}", o.opt) + ;; + ;; + std.sbfmt(sb, "] ") + for o in def.opts + if o.arg.len != 0 + std.sbfmt(sb, "[-{} {}] ", o.opt, o.arg) + ;; + ;; + std.sbfmt(sb, "{}\n", def.argdesc) + std.sbfmt(sb, "\t-h\tprint this help message\n") + std.sbfmt(sb, "\t-?\tprint this help message\n") + for o in def.opts + std.sbfmt(sb, "\t-{}{}{}\t{}\n", o.opt, sep(o.arg), o.arg, o.desc) + ;; + s = sbfin(sb) + write(1, s) + slfree(s) +} + +const sep = {s + if s.len > 0 + -> " " + else + -> "" + ;; +} diff --git a/lib/std/pathjoin.myr b/lib/std/pathjoin.myr new file mode 100644 index 0000000..f9df8aa --- /dev/null +++ b/lib/std/pathjoin.myr @@ -0,0 +1,105 @@ +use "alloc.use" +use "extremum.use" +use "strjoin.use" +use "strsplit.use" +use "sleq.use" +use "sljoin.use" +use "sldup.use" +use "slcp.use" +use "die.use" +use "fmt.use" + +pkg std = + const pathcat : (a : byte[:], b : byte[:] -> byte[:]) + const pathjoin : (p : byte[:][:] -> byte[:]) + const pathnorm : (p : byte[:] -> byte[:]) +;; + +const pathcat = {a, b + -> pathjoin([a, b][:]) +} + +const pathjoin = {l + var p, i, q + + for i = 0; i < l.len; i++ + if l[i].len != 0 + break + ;; + ;; + p = strjoin(l[i:], "/") + q = pathnorm(p) + slfree(p) + -> q +} + +const pathnorm = {p + var comps + var i, del, dst + var s, ret + + comps = strsplit(p, "/") + /* + "." is a no-op component, so we drop it. In order + to drop a component, we set it to the empty string, + and remove it later on in the code. + */ + for i = 0; i < comps.len; i++ + if sleq(comps[i], ".") + comps[i] = "" + ;; + ;; + + /* + then, resolve '..' by cancelling out previous components. Scan + backwards in the component list for the first real component, + and delete both it and the '..' that lead to it. + + Leave in extra '..' components, so that, eg, ../foo doesn't + get mangled. + */ + for i = 0; i < comps.len; i++ + if !sleq(comps[i], "..") + continue + ;; + for del = 1; del <= i; del++ + if comps[i - del].len > 0 && !sleq(comps[i-del], "..") + comps[i - del] = "" + comps[i] = "" + break + ;; + ;; + ;; + + /* clear out the path nodes we decided to drop */ + dst = 0 + for i = 0; i < comps.len; i++ + if comps[i].len > 0 + comps[dst++] = comps[i] + ;; + ;; + comps = comps[:dst] + + /* + and reassemble. If we have an absolute path, + make it absolute. If we have an empty path, return + ".". Otherwise, just return the path. + */ + if p.len > 0 && sleq(p[:1], "/") + for i = 0; i < comps.len; i++ + if !sleq(comps[i], "..") + break + ;; + ;; + s = strjoin(comps[i:], "/") + ret = fmt("/{}", s) + slfree(s) + elif comps.len == 0 + ret = sldup(".") + else + ret = strjoin(comps, "/") + ;; + slfree(comps) + -> ret +} + diff --git a/lib/std/putint.myr b/lib/std/putint.myr new file mode 100644 index 0000000..711001d --- /dev/null +++ b/lib/std/putint.myr @@ -0,0 +1,44 @@ +use "types.use" +use "die.use" + +pkg std = + generic putle64 : (buf : byte[:], v : @a::(numeric,integral) -> size) + generic putbe64 : (buf : byte[:], v : @a::(numeric,integral) -> size) + generic putle32 : (buf : byte[:], v : @a::(numeric,integral) -> size) + generic putbe32 : (buf : byte[:], v : @a::(numeric,integral) -> size) + generic putle16 : (buf : byte[:], v : @a::(numeric,integral) -> size) + generic putbe16 : (buf : byte[:], v : @a::(numeric,integral) -> size) + generic putle8 : (buf : byte[:], v : @a::(numeric,integral) -> size) + generic putbe8 : (buf : byte[:], v : @a::(numeric,integral) -> size) +;; + +generic putle64 = {buf, v; -> putle(buf, v castto(uint64), 8)} +generic putbe64 = {buf, v; -> putbe(buf, v castto(uint64), 8)} +generic putle32 = {buf, v; -> putle(buf, v castto(uint64), 4)} +generic putbe32 = {buf, v; -> putbe(buf, v castto(uint64), 4)} +generic putle16 = {buf, v; -> putle(buf, v castto(uint64), 2)} +generic putbe16 = {buf, v; -> putbe(buf, v castto(uint64), 2)} +generic putle8 = {buf, v; -> putle(buf, v castto(uint64), 1)} +generic putbe8 = {buf, v; -> putbe(buf, v castto(uint64), 1)} + +const putbe = {buf, val, n + var i, k + + assert(buf.len >= n, "buffer too small") + for i = 0; i < n; i++ + k = val >> (8*(n-i-1)) + buf[i] = (k & 0xff) castto(byte) + ;; + -> n castto(size) +} + +const putle = {buf, val, n + var i + + assert(buf.len >= n, "buffer too small") + for i = 0; i < n; i++ + buf[i] = (val & 0xff) castto(byte) + val >>= 8 + ;; + -> n castto(size) +} diff --git a/lib/std/rand.myr b/lib/std/rand.myr new file mode 100644 index 0000000..2e8c73e --- /dev/null +++ b/lib/std/rand.myr @@ -0,0 +1,185 @@ +use "die.use" +use "types.use" +use "alloc.use" +/* + Translated from C by Ori Bernstein + */ + +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) + */ + +pkg std = + type rng + + const mksrng : (seed : uint32 -> rng#) + const delrng : (rng : rng# -> void) + generic rand : (rng : rng#, lo : @a::(numeric,integral), hi : @a::(numeric,integral) -> @a::(numeric,integral)) + generic randN : (rng : rng# -> @a::(numeric,integral)) + const randbytes : (rng : rng#, buf : byte[:] -> size) + const rand32 : (rng : rng# -> uint32) +;; + +type rng = struct + state : uint32[624] + i : uint32 +;; + +/* allocates and initializes a random number generator */ +const mksrng = {seed + var rng + + rng = alloc() + init(rng, seed) + -> rng +} + +const delrng = {rng + free(rng) +} + +/* initializes a random number generator from the seed `seed`. */ +const init = {rng, seed + var i + + for i = 0; i < 624; i++ + rng.state[i] = seed + seed = 1812433253 * (seed ^ (seed >> 30)) + i + 1 + ;; + rng.i = i +} + +/* + Generates a random integer from `rng` in the range [lo, hi), + returning the value. The range [lo, hi) must be positive, + nonempty, and the difference between hi and lo must be + less then 2^(type_bits - 1) +*/ +generic rand = {rng, lo, hi -> @a::(integral,numeric) + var span, lim + var maxrand + var val + + assert(hi - lo > 0, "rand.myr: range for random values must be >= 1") + + span = hi - lo + maxrand = (1 << (8*sizeof(@a))) - 1 /* max for signed value */ + if maxrand < 0 /* signed */ + maxrand = (1 << (8*sizeof(@a)-1)) - 1 /* max for signed value */ + ;; + + lim = (maxrand/span)*span + val = (randN(rng) & maxrand) + while val > lim + val = (randN(rng) & maxrand) + ;; + -> val % span + lo +} + +/* + Generates a random integer of any size from the + random number generator `rng`. The returned value + may be negative, if the type is signed. +*/ +generic randN = {rng -> @a::(integral,numeric) + var i, val + + val = 0 + for i = 0; i < sizeof(@a)/4; i++ + val <<= 8*sizeof(@a) + val |= rand32(rng) castto(@a::(integral,numeric)) + ;; + -> val +} + +/* + generates a 32 bit unsigned random number + from the random number generator `rng`. +*/ +const rand32 = {rng + var x + + if rng.i == 624 + next(rng) + ;; + x = rng.state[rng.i] + rng.i++ + + x ^= x >> 11 + x ^= (x << 7) & 0x9D2C5680 + x ^= (x << 15) & 0xEFC60000 + -> x ^ (x >> 18) +} + +const randbytes = {rng, buf + var i, n, r + + n = 0 + for i = 0; i < buf.len/4; i++ + r = rand32(rng) + buf[n++] = (r >> 0 & 0xff) castto(byte) + buf[n++] = (r >> 8 & 0xff) castto(byte) + buf[n++] = (r >> 16 & 0xff) castto(byte) + buf[n++] = (r >> 32 & 0xff) castto(byte) + ;; + r = rand32(rng) + for ; n != buf.len; n++ + buf[n++] = (r & 0xff) castto(byte) + r >>= 8 + ;; + -> n + +} + +/* updates random number generator state when we tick over. */ +const next = {rng + var k + var y + + for k = 0; k < 227; k++ + y = (rng.state[k] & 0x80000000) | (rng.state[k + 1] & 0x7FFFFFFF) + rng.state[k] = rng.state[k + 397] ^ (y >> 1) ^ ((y & 1) * 0x9908B0DF) + ;; + for ; k < 623; k++ + y = (rng.state[k] & 0x80000000) | (rng.state[k + 1] & 0x7FFFFFFF) + rng.state[k] = rng.state[k - 227] ^ (y >> 1) ^ ((y & 1) * 0x9908B0DF); + ;; + y = (rng.state[623] & 0x80000000) | (rng.state[0] & 0x7FFFFFFF) + rng.state[623] = rng.state[396] ^ (y >> 1) ^ ((y & 1) * 0x9908B0DF); + rng.i = 0 +} diff --git a/lib/std/resolve+plan9.myr b/lib/std/resolve+plan9.myr new file mode 100644 index 0000000..ef73843 --- /dev/null +++ b/lib/std/resolve+plan9.myr @@ -0,0 +1,2 @@ +pkg std = +;; diff --git a/lib/std/resolve+posixy.myr b/lib/std/resolve+posixy.myr new file mode 100644 index 0000000..185c9d7 --- /dev/null +++ b/lib/std/resolve+posixy.myr @@ -0,0 +1,443 @@ +use sys +use "alloc.use" +use "chartype.use" +use "die.use" +use "endian.use" +use "result.use" +use "extremum.use" +use "hashfuncs.use" +use "htab.use" +use "ipparse.use" +use "option.use" +use "slcp.use" +use "sleq.use" +use "slpush.use" +use "slurp.use" +use "strfind.use" +use "strsplit.use" +use "strstrip.use" +use "types.use" +use "utf.use" + +pkg std = + type rectype = uint16 + + const DnsA : rectype = 1 /* host address */ + const DnsNS : rectype = 2 /* authoritative name server */ + const DnsMD : rectype = 3 /* mail destination (Obsolete - use MX) */ + const DnsMF : rectype = 4 /* mail forwarder (Obsolete - use MX) */ + const DnsCNAME : rectype = 5 /* canonical name for an alias */ + const DnsSOA : rectype = 6 /* marks the start of a zone of authority */ + const DnsMB : rectype = 7 /* mailbox domain name (EXPERIMENTAL) */ + const DnsMG : rectype = 8 /* mail group member (EXPERIMENTAL) */ + const DnsMR : rectype = 9 /* mail rename domain name (EXPERIMENTAL) */ + const DnsNULL : rectype = 10 /* null RR (EXPERIMENTAL) */ + const DnsWKS : rectype = 11 /* well known service description */ + const DnsPTR : rectype = 12 /* domain name pointer */ + const DnsHINFO : rectype = 13 /* host information */ + const DnsMINFO : rectype = 14 /* mailbox or mail list information */ + const DnsMX : rectype = 15 /* mail exchange */ + const DnsTXT : rectype = 16 /* text strings */ + const DnsAAAA : rectype = 28 /* ipv6 host address */ + + + type resolveerr = union + `Badhost + `Badsrv + `Badquery + `Badresp + ;; + + type hostinfo = struct + fam : sys.sockfam + stype : sys.socktype + ttl : uint32 + addr : netaddr + /* + flags : uint32 + addr : sockaddr[:] + canon : byte[:] + */ + ;; + + const resolve : (host : byte[:] -> result(hostinfo[:], resolveerr)) + const resolvemx : (host : byte[:] -> result(hostinfo[:], resolveerr)) + const resolverec : (host : byte[:], t : rectype -> result(hostinfo[:], resolveerr)) +;; + +const Hostfile = "/etc/hosts" +const Resolvfile = "/etc/resolv.conf" + +var hostmap : htab(byte[:], hostinfo)# +var search : byte[:][:] +var nameservers : netaddr[:] + +const __init__ = { + hostmap = mkht(strhash, streq) + loadhosts() + loadresolv() +} + +const resolve = {host + -> resolverec(host, DnsA) +} + +const resolvemx = {host + -> resolverec(host, DnsMX) +} + +const resolverec = {host, t + match hostfind(host) + | `Some hinf: + -> `Ok slpush([][:], hinf) + | `None: + -> dnsresolve(host, DnsA) + ;; +} + +const hostfind = {host + -> htget(hostmap, host) +} + +const loadhosts = { + var h + var lines + + match slurp(Hostfile) + | `Ok d: h = d + | `Fail m: -> + ;; + + lines = strsplit(h, "\n") + for l in lines + /* trim comment */ + match strfind(l, "#") + | `Some idx: l = l[:idx] + | `None: /* whole line */ + ;; + + match word(l) + | `Some (ip, rest): + match ipparse(ip) + | `Some addr: + addhosts(addr, ip, rest) + | `None: + /* + invalid addresses are ignored: we don't want to break stuff + with invalid or unsupported addresses + */ + + ;; + | `None: + ;; + ;; + slfree(lines) +} + +const addhosts = {addr, as, str + var hinf + var fam + + match addr + | `Ipv4 _: fam = sys.Afinet + | `Ipv6 _: fam = sys.Afinet6 + ;; + while true + match word(str) + | `Some (name, rest): + str = rest + if hthas(hostmap, name) + continue + ;; + hinf = [ + .fam=fam, + .stype = 0, + .ttl = 0, + .addr = addr + ] + htput(hostmap, name, hinf) + | `None: + -> + ;; + ;; +} + +const loadresolv = { + var h + var lines + + match slurp(Resolvfile) + | `Ok d: h = d + | `Fail m: -> + ;; + + lines = strsplit(h, "\n") + for l in lines + match strfind(l, "#") + | `Some _idx: l = l[:_idx] + | `None: + ;; + + match word(l) + | `Some ("nameserver", srv): + addns(srv) + | `Some (_, rest): + /* invalid or unrecognized commands */ + | `None: + /* unrecognized lines */ + ;; + ;; + slfree(lines) +} + +const addns = {rest + match word(rest) + | `Some (name, _): + match ipparse(name) + | `Some addr: + nameservers = slpush(nameservers, addr) + | `None: + /* nothing */ + ;; + | `None: + /* nothing */ + ;; +} + +const word = {s + var c, len + + len = 0 + s = strfstrip(s) + for c = decode(s[len:]); c != Badchar && !isblank(c); c = decode(s[len:]) + len += charlen(c) + ;; + if len == 0 + -> `None + else + -> `Some (s[:len], s[len:]) + ;; +} + + +const dnsresolve = {host, t + var nsrv + + if !valid(host) + -> `Fail (`Badhost) + ;; + for ns in nameservers + nsrv = dnsconnect(ns) + if nsrv >= 0 + -> dnsquery(nsrv, host, t) + ;; + ;; + -> `Fail (`Badsrv) +} + +const dnsconnect = {ns + match ns + | `Ipv4 addr: -> dnsconnectv4(addr) + | `Ipv6 addr: die("don't support ipv6 yet\n") + ;; +} + +const dnsconnectv4 = {addr + var sa : sys.sockaddr_in + var s + var status + + s = sys.socket(sys.Afinet, sys.Sockdgram, 0) + if s < 0 + -> -1 + ;; + sa.fam = sys.Afinet + sa.port = hosttonet(53) + sa.addr = addr + status = sys.connect(s, (&sa) castto(sys.sockaddr#), sizeof(sys.sockaddr_in)) + if status < 0 + -> -1 + ;; + -> s +} + +const dnsquery = {srv, host, t + var id + var r + + id = tquery(srv, host, t) + r = rquery(srv, id) + -> r +} + +const Qr : uint16 = 1 << 0 +const Aa : uint16 = 1 << 5 +const Tc : uint16 = 1 << 6 +const Rd : uint16 = 1 << 7 +const Ra : uint16 = 1 << 8 + +var nextid : uint16 = 42 +const tquery = {srv, host, t + var pkt : byte[512] /* big enough */ + var off : size + + /* header */ + off = 0 + off += pack16(pkt[:], off, nextid) /* id */ + off += pack16(pkt[:], off, Ra) /* flags */ + off += pack16(pkt[:], off, 1) /* qdcount */ + off += pack16(pkt[:], off, 0) /* ancount */ + off += pack16(pkt[:], off, 0) /* nscount */ + off += pack16(pkt[:], off, 0) /* arcount */ + + /* query */ + off += packname(pkt[:], off, host) /* host */ + off += pack16(pkt[:], off, t castto(uint16)) /* qtype: a record */ + off += pack16(pkt[:], off, 0x1) /* qclass: inet4 */ + + sys.write(srv, pkt[:off]) + -> nextid++ +} + +const rquery = {srv, id + var pktbuf : byte[1024] + var pkt + var n + + n = sys.read(srv, pktbuf[:]) + if n < 0 + ;; + pkt = pktbuf[:n] + -> hosts(pkt, id) +} + +const hosts = {pkt, id : uint16 + var off + var v, q, a + var i + var hinf : hostinfo[:] + + off = 0 + /* parse header */ + (v, off) = unpack16(pkt, off) /* id */ + if v != id + -> `Fail (`Badresp) + ;; + (v, off) = unpack16(pkt, off) /* flags */ + (q, off) = unpack16(pkt, off) /* qdcount */ + (a, off) = unpack16(pkt, off) /* ancount */ + (v, off) = unpack16(pkt, off) /* nscount */ + (v, off) = unpack16(pkt, off) /* arcount */ + + /* skip past query records */ + for i = 0; i < q; i++ + off = skipname(pkt, off) /* name */ + (v, off) = unpack16(pkt, off) /* type */ + (v, off) = unpack16(pkt, off) /* class */ + ;; + + /* parse answer records */ + hinf = slalloc(a castto(size)) + for i = 0; i < a; i++ + off = skipname(pkt, off) /* name */ + (v, off) = unpack16(pkt, off) /* type */ + (v, off) = unpack16(pkt, off) /* class */ + (hinf[i].ttl, off) = unpack32(pkt, off) /* ttl */ + (v, off) = unpack16(pkt, off) /* rdatalen */ + /* the thing we're interested in: our IP address */ + hinf[i].addr = `Ipv4 [pkt[off], pkt[off+1], pkt[off+2], pkt[off+3]] + off += 4; + ;; + -> `Ok hinf +} + + +const skipname = {pkt, off + var sz + + for sz = pkt[off] castto(size); sz != 0; sz = pkt[off] castto(size) + /* ptr is 2 bytes */ + if sz & 0xC0 == 0xC0 + -> off + 2 + else + off += sz + 1 + ;; + ;; + -> off + 1 +} + + +const pack16 = {buf, off, v + buf[off] = (v & 0xff00) >> 8 castto(byte) + buf[off+1] = (v & 0x00ff) castto(byte) + -> sizeof(uint16) /* we always write one uint16 */ +} + +const unpack16 = {buf, off + var v + + v = (buf[off] castto(uint16)) << 8 + v |= (buf[off + 1] castto(uint16)) + -> (v, off+sizeof(uint16)) +} + +const unpack32 = {buf, off + var v + + v = (buf[off] castto(uint32)) << 24 + v |= (buf[off+1] castto(uint32)) << 32 + v |= (buf[off+2] castto(uint32)) << 8 + v |= (buf[off+3] castto(uint32)) + -> (v, off+sizeof(uint32)) +} + +const packname = {buf, off : size, host + var i + var start + var last + + start = off + last = 0 + for i = 0; i < host.len; i++ + if host[i] == ('.' castto(byte)) + off += addseg(buf, off, host[last:i]) + last = i + 1 + ;; + ;; + if host[host.len - 1] != ('.' castto(byte)) + off += addseg(buf, off, host[last:]) + ;; + off += addseg(buf, off, "") /* null terminating segment */ + -> off - start +} + +const addseg = {buf, off, str + buf[off] = str.len castto(byte) + slcp(buf[off + 1 : off + str.len + 1], str) + -> str.len + 1 +} + +const valid = {host : byte[:] + var i + var seglen + + /* maximum length: 255 chars */ + if host.len > 255 + -> false + ;; + + seglen = 0 + for i = 0; i < host.len; i++ + if host[i] == ('.' castto(byte)) + seglen = 0 + ;; + if seglen > 63 + -> false + ;; + if host[i] & 0x80 != 0 + -> false + ;; + ;; + + -> true +} diff --git a/lib/std/result.myr b/lib/std/result.myr new file mode 100644 index 0000000..58ef45b --- /dev/null +++ b/lib/std/result.myr @@ -0,0 +1,9 @@ +use "die.use" + +pkg std = + type result(@a, @b) = union + `Ok @a + `Fail @b + ;; +;; + diff --git a/lib/std/search.myr b/lib/std/search.myr new file mode 100644 index 0000000..725e419 --- /dev/null +++ b/lib/std/search.myr @@ -0,0 +1,43 @@ +use "cmp.use" +use "option.use" + +pkg std = + generic lsearch : (sl : @t[:], val : @t, cmp : (a : @t, b : @t -> order) -> option(@idx::(integral,numeric))) + generic bsearch : (sl : @t[:], val : @t, cmp : (a : @t, b : @t -> order) -> option(@idx::(integral,numeric))) +;; + +/* linear search over a list of values */ +generic lsearch = {sl, val, cmp + var i + + for i = 0; i < sl.len; i++ + match cmp(sl[i], val) + | `Equal: + -> `Some i + | _: + /* nothing */ + ;; + ;; + -> `None +} + +/* binary search over a sorted list of values. */ +generic bsearch = {sl, val, cmp + var hi, lo, mid + + lo = 0 + hi = sl.len - 1 + + while lo <= hi + mid = (hi + lo) / 2 + match cmp(val, sl[mid]) + | `Before: hi = mid - 1 + | `After: lo = mid + 1 + | `Equal: + -> `Some mid + ;; + ;; + -> `None +} + + diff --git a/lib/std/slcp.myr b/lib/std/slcp.myr new file mode 100644 index 0000000..1035a29 --- /dev/null +++ b/lib/std/slcp.myr @@ -0,0 +1,26 @@ +use "die.use" +use "types.use" + +pkg std = + generic slcp : (a : @a[:], b : @a[:] -> void) +;; + +generic slcp = {a : @a[:], b : @a[:] + var i + var addr_a, addr_b + + assert(a.len == b.len, "arguments to slcp() must be of equal l |