hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 8036a75d67709f13f3aa85a9b4fea091f8b5fc9d
parent 2d20726b2e39af479b43cc3cc271453948923a19
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 14 May 2022 12:27:57 +0200

cmd/ioctlgen: initial commit

An internal tool for generating ioctl numbers.

Diffstat:
Acmd/ioctlgen/main.ha | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 137 insertions(+), 0 deletions(-)

diff --git a/cmd/ioctlgen/main.ha b/cmd/ioctlgen/main.ha @@ -0,0 +1,137 @@ +use bufio; +use fmt; +use hare::ast; +use hare::lex; +use hare::lex::{ltok}; +use hare::parse; +use hare::types; +use io; +use os; +use regex; +use strings; + +let ioctlre: regex::regex = regex::regex { ... }; + +@init fn init() void = { + ioctlre = regex::compile(`@(_IO[RW]*)\((.*)\)`)!; +}; + +@fini fn fini() void = { + regex::regex_finish(&ioctlre); +}; + +type dir = enum u64 { + IO = 0, + IOW = 1, + IOR = 2, + IOWR = IOW | IOR, +}; + +type ioctl = (dir, rune, u64, const nullable *types::_type); + +export fn main() void = { + // TODO: Configurable arch + const store = types::store(types::x86_64, null, null); + defer types::store_free(store); + + for (true) { + const line = match (bufio::scanline(os::stdin)!) { + case io::EOF => + break; + case let line: []u8 => + yield strings::fromutf8(line); + }; + defer free(line); + + let groups = match (regex::find(&ioctlre, line)!) { + case void => + fmt::println(line)!; + continue; + case let mg: []regex::matchgroup => + yield mg; + }; + defer free(groups); + + const dir = switch (groups[1].content) { + case "_IO" => + yield dir::IO; + case "_IOR" => + yield dir::IOR; + case "_IOW" => + yield dir::IOW; + case "_IOWR" => + yield dir::IOWR; + }; + const ioctl = parseioctl(store, dir, groups[2].content); + + const prefix = strings::sub(line, 0, groups[1].start - 1); + fmt::printfln("{}{};", prefix, ioctlno(&ioctl))!; + }; +}; + +fn parseioctl(store: *types::typestore, d: dir, params: str) ioctl = { + const buf = bufio::fixed(strings::toutf8(params), io::mode::READ); + const lex = lex::init(&buf, "<ioctl>"); + + const rn = expect(&lex, ltok::LIT_RUNE).1 as rune; + expect(&lex, ltok::COMMA); + const num = expect(&lex, ltok::LIT_ICONST).1 as i64; + + if (d == dir::IO) { + return (d, rn, num: u64, null); + }; + + expect(&lex, ltok::COMMA); + const ty = match (parse::_type(&lex)) { + case let ty: ast::_type => + yield ty; + case let err: parse::error => + fmt::fatal("Error:", parse::strerror(err)); + }; + + const ty = match (types::lookup(store, &ty)) { + case let err: types::error => + fmt::fatal("Error:", types::strerror(err)); + case types::deferred => + fmt::fatal("Error: this tool does not support reverse declarations"); + case let ty: const *types::_type => + yield ty; + }; + + return (d, rn, num: u64, ty); +}; + +fn expect(lex: *lex::lexer, want: ltok) lex::token = { + match (lex::lex(lex)) { + case let err: lex::error => + fmt::fatal("Error:", lex::strerror(err)); + case let tok: lex::token => + if (tok.0 != want) { + fmt::fatalf("Error: unexpected {}", lex::tokstr(tok)); + }; + return tok; + }; +}; + +def IOC_NRBITS: u64 = 8; +def IOC_TYPEBITS: u64 = 8; +def IOC_SIZEBITS: u64 = 14; // XXX: Arch-specific +def IOC_DIRBITS: u64 = 2; // XXX: Arch-specific + +def IOC_NRSHIFT: u64 = 0; +def IOC_TYPESHIFT: u64 = IOC_NRSHIFT + IOC_NRBITS; +def IOC_SIZESHIFT: u64 = IOC_TYPESHIFT + IOC_TYPEBITS; +def IOC_DIRSHIFT: u64 = IOC_SIZESHIFT + IOC_SIZEBITS; + +fn ioctlno(io: *ioctl) u64 = { + const ty = match (io.3) { + case let ty: const *types::_type => + yield ty.sz; + case null => + yield 0z; + }; + return (io.0: u64 << IOC_DIRSHIFT) | + (io.1: u32: u64 << IOC_TYPESHIFT) | + (io.2 << IOC_NRSHIFT) | + (ty: u64 << IOC_SIZESHIFT); +};