Compare commits
5 Commits
100b752eee
...
2f632077b8
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f632077b8 | |||
| 21aabca9f7 | |||
| 9f4c494e09 | |||
| 3f9df4a32f | |||
| 4a60c1fc12 |
@@ -47,9 +47,7 @@ func chip8_create[] : CHIP8
|
|||||||
|
|
||||||
func chip8_disassemble[c: CHIP8, ins_count: i64] : void
|
func chip8_disassemble[c: CHIP8, ins_count: i64] : void
|
||||||
for i in 0..ins_count
|
for i in 0..ins_count
|
||||||
io.print("0x")
|
io.printf("0x%x: ", c->pc)
|
||||||
io.print_i64_hex(c->pc)
|
|
||||||
io.print(": ")
|
|
||||||
|
|
||||||
let high: i64 = c->memory[c->pc]
|
let high: i64 = c->memory[c->pc]
|
||||||
let low: i64 = c->memory[c->pc + 1]
|
let low: i64 = c->memory[c->pc + 1]
|
||||||
@@ -69,179 +67,82 @@ func chip8_disassemble[c: CHIP8, ins_count: i64] : void
|
|||||||
else if nnn == 0x0ee
|
else if nnn == 0x0ee
|
||||||
io.println("RET")
|
io.println("RET")
|
||||||
else
|
else
|
||||||
io.print("SYS ")
|
io.printf("SYS %d\n", nnn)
|
||||||
io.println_i64(nnn)
|
|
||||||
else if op == 0x1
|
else if op == 0x1
|
||||||
io.print("JP 0x")
|
io.printf("JP 0x%x\n", nnn)
|
||||||
io.print_i64_hex(nnn)
|
|
||||||
io.print("\n")
|
|
||||||
else if op == 0x2
|
else if op == 0x2
|
||||||
io.print("CALL ")
|
io.printf("CALL %d\n", nnn)
|
||||||
io.println_i64(nnn)
|
|
||||||
else if op == 0x3
|
else if op == 0x3
|
||||||
io.print("SE V")
|
io.printf("SE V%x, %d\n", x, kk)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", ")
|
|
||||||
io.println_i64(kk)
|
|
||||||
else if op == 0x4
|
else if op == 0x4
|
||||||
io.print("SNE V")
|
io.printf("SNE V%x, %d\n", x, kk)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", ")
|
|
||||||
io.println_i64(kk)
|
|
||||||
else if op == 0x5
|
else if op == 0x5
|
||||||
io.print("SE V")
|
io.printf("SE V%x, V%x\n", x, y)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print("\n")
|
|
||||||
else if op == 0x6
|
else if op == 0x6
|
||||||
io.print("LD V")
|
io.printf("LD V%x, %d\n", x, kk)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", ")
|
|
||||||
io.println_i64(kk)
|
|
||||||
else if op == 0x7
|
else if op == 0x7
|
||||||
io.print("ADD V")
|
io.printf("ADD V%x, %d\n", x, kk)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", ")
|
|
||||||
io.println_i64(kk)
|
|
||||||
else if op == 0x8
|
else if op == 0x8
|
||||||
if n == 0x0
|
if n == 0x0
|
||||||
io.print("LD V")
|
io.printf("LD V%x, V%x\n", x, y)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print("\n")
|
|
||||||
else if n == 0x1
|
else if n == 0x1
|
||||||
io.print("OR V")
|
io.printf("OR V%x, V%x\n", x, y)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print("\n")
|
|
||||||
else if n == 0x2
|
else if n == 0x2
|
||||||
io.print("AND V")
|
io.printf("AND V%x, V%x\n", x, y)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print("\n")
|
|
||||||
else if n == 0x3
|
else if n == 0x3
|
||||||
io.print("XOR V")
|
io.printf("XOR V%x, V%x\n", x, y)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print("\n")
|
|
||||||
else if n == 0x4
|
else if n == 0x4
|
||||||
io.print("ADD V")
|
io.printf("ADD V%x, V%x\n", x, y)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print("\n")
|
|
||||||
else if n == 0x5
|
else if n == 0x5
|
||||||
io.print("SUB V")
|
io.printf("SUB V%x, V%x\n", x, y)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print("\n")
|
|
||||||
else if n == 0x6
|
else if n == 0x6
|
||||||
io.print("SHR V")
|
io.printf("SHR V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else if n == 0x7
|
else if n == 0x7
|
||||||
io.print("SUBN V")
|
io.printf("SUBN V%x, V%x\n", x, y)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print("\n")
|
|
||||||
else if n == 0xE
|
else if n == 0xE
|
||||||
io.print("SHL V")
|
io.printf("SHL V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else
|
else
|
||||||
io.print("??? (")
|
io.printf("??? (%x)\n", ins)
|
||||||
io.print_i64_hex(ins)
|
|
||||||
io.println(")")
|
|
||||||
else if op == 0x9
|
else if op == 0x9
|
||||||
io.print("SNE V")
|
io.printf("SNE V%x, V%x\n", x, y)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print("\n")
|
|
||||||
else if op == 0xa
|
else if op == 0xa
|
||||||
io.print("LD I, 0x")
|
io.printf("LD I, 0x%x\n", nnn)
|
||||||
io.print_i64_hex(nnn)
|
|
||||||
io.print("\n")
|
|
||||||
else if op == 0xb
|
else if op == 0xb
|
||||||
io.print("JP V0, ")
|
io.printf("JP V0, %d\n", nnn)
|
||||||
io.println_i64(nnn)
|
|
||||||
else if op == 0xc
|
else if op == 0xc
|
||||||
io.print("RND V")
|
io.printf("RND V%x, %d\n", x, kk)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", ")
|
|
||||||
io.println_i64(kk)
|
|
||||||
else if op == 0xd
|
else if op == 0xd
|
||||||
io.print("DRW V")
|
io.printf("DRW V%x, V%x, %d\n", x, y, n)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print(", V")
|
|
||||||
io.print_i64_hex(y)
|
|
||||||
io.print(", ")
|
|
||||||
io.println_i64(n)
|
|
||||||
else if op == 0xe
|
else if op == 0xe
|
||||||
if kk == 0x9e
|
if kk == 0x9e
|
||||||
io.print("SKP V")
|
io.printf("SKP V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else if kk == 0xa1
|
else if kk == 0xa1
|
||||||
io.print("SKNP V")
|
io.printf("SKNP V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else
|
else
|
||||||
io.print("??? (")
|
io.printf("??? (%x)\n", ins)
|
||||||
io.print_i64_hex(ins)
|
|
||||||
io.println(")")
|
|
||||||
else if op == 0xf
|
else if op == 0xf
|
||||||
if kk == 0x07
|
if kk == 0x07
|
||||||
io.print("LD V")
|
io.printf("LD V%x, DT\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.println(", DT")
|
|
||||||
else if kk == 0x0A
|
else if kk == 0x0A
|
||||||
io.print("LD V")
|
io.printf("LD V%x, K\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.println(", K")
|
|
||||||
else if kk == 0x15
|
else if kk == 0x15
|
||||||
io.print("LD DT, V")
|
io.printf("LD DT, V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else if kk == 0x18
|
else if kk == 0x18
|
||||||
io.print("LD ST, V")
|
io.printf("LD ST, V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else if kk == 0x1E
|
else if kk == 0x1E
|
||||||
io.print("ADD I, V")
|
io.printf("ADD I, V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else if kk == 0x29
|
else if kk == 0x29
|
||||||
io.print("LD F, V")
|
io.printf("LD F, V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else if kk == 0x33
|
else if kk == 0x33
|
||||||
io.print("LD B, V")
|
io.printf("LD B, V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else if kk == 0x55
|
else if kk == 0x55
|
||||||
io.print("LD [I], V")
|
io.printf("LD [I], V%x\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.print("\n")
|
|
||||||
else if kk == 0x65
|
else if kk == 0x65
|
||||||
io.print("LD V")
|
io.printf("LD V%x, [I]\n", x)
|
||||||
io.print_i64_hex(x)
|
|
||||||
io.println(", [I]")
|
|
||||||
else
|
else
|
||||||
io.print("??? (")
|
io.printf("??? (%x)\n", ins)
|
||||||
io.print_i64_hex(ins)
|
|
||||||
io.println(")")
|
|
||||||
else
|
else
|
||||||
io.print("??? (")
|
io.printf("??? (%x)\n", ins)
|
||||||
io.print_i64_hex(ins)
|
|
||||||
io.println(")")
|
|
||||||
|
|
||||||
func chip8_step[c: CHIP8] : void
|
func chip8_step[c: CHIP8] : void
|
||||||
let high: i64 = c->memory[c->pc]
|
let high: i64 = c->memory[c->pc]
|
||||||
@@ -419,4 +320,4 @@ func main[argc: i64, argv: ptr] : i64
|
|||||||
if c->display[x + y * 64] == 1
|
if c->display[x + y * 64] == 1
|
||||||
DrawRectangle(x * 10, y * 10, 10, 10, 0xff000000)
|
DrawRectangle(x * 10, y * 10, 10, 10, 0xff000000)
|
||||||
|
|
||||||
EndDrawing()
|
EndDrawing()
|
||||||
|
|||||||
79
examples/curl.zr
Normal file
79
examples/curl.zr
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
func main[argc: i64, argv: ptr] : i64
|
||||||
|
if argc < 2
|
||||||
|
io.println("ERROR: url is missing")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
let url: str = mem.read64(argv + 8)
|
||||||
|
|
||||||
|
if str.len(url) <= 7
|
||||||
|
io.println("ERROR: invalid url (Did you forget \"http://\"?)")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if !str.equal(str.substr(url, 0, 7), "http://")
|
||||||
|
io.println("ERROR: only http scheme is supported")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
let url_len: i64 = str.len(url)
|
||||||
|
let host_start = 7
|
||||||
|
let i: i64 = host_start
|
||||||
|
while i < url_len
|
||||||
|
if url[i] == '/'
|
||||||
|
break
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
let host: str = str.substr(url, host_start, i - host_start)
|
||||||
|
let path: str = "/"
|
||||||
|
if i < url_len
|
||||||
|
path = str.substr(url, i, url_len - i)
|
||||||
|
|
||||||
|
let addr: i64 = net.resolve(host)
|
||||||
|
if addr <= 0
|
||||||
|
io.println("ERROR: domain resolution failed")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
let s: i64 = net.connect(addr, 80)
|
||||||
|
if s < 0
|
||||||
|
io.println("ERROR: connection failed")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
// TODO: add string builder to std
|
||||||
|
let req: str = "GET "
|
||||||
|
req = str.concat(req, path)
|
||||||
|
req = str.concat(req, " HTTP/1.0\r\nHost: ")
|
||||||
|
req = str.concat(req, host)
|
||||||
|
req = str.concat(req, "\r\nConnection: close\r\n\r\n")
|
||||||
|
net.send(s, req, str.len(req))
|
||||||
|
mem.free(req)
|
||||||
|
|
||||||
|
let header_buf: str = mem.alloc(8192)
|
||||||
|
let header_size = 0
|
||||||
|
let found: bool = false
|
||||||
|
let end_index: i64 = -1
|
||||||
|
|
||||||
|
while !found && header_size < 8192
|
||||||
|
let n: i64 = net.read(s, header_buf + header_size, 8192 - header_size)
|
||||||
|
if n <= 0
|
||||||
|
break
|
||||||
|
let current_size: i64 = header_size + n
|
||||||
|
i = 0
|
||||||
|
while i <= current_size - 4
|
||||||
|
if header_buf[i] == '\r' && header_buf[i + 1] == '\n' && header_buf[i + 2] == '\r' && header_buf[i + 3] == '\n'
|
||||||
|
found = true
|
||||||
|
end_index = i + 4
|
||||||
|
break
|
||||||
|
i = i + 1
|
||||||
|
header_size = current_size
|
||||||
|
|
||||||
|
if end_index < header_size
|
||||||
|
io.print_sized(header_buf + end_index, header_size - end_index)
|
||||||
|
mem.free(header_buf)
|
||||||
|
|
||||||
|
let buffer: ptr = mem.alloc(4096)
|
||||||
|
while true
|
||||||
|
let n: i64 = net.read(s, buffer, 4096)
|
||||||
|
if n <= 0
|
||||||
|
break
|
||||||
|
io.print_sized(buffer, n)
|
||||||
|
mem.free(buffer)
|
||||||
|
|
||||||
|
net.close(s)
|
||||||
@@ -4,4 +4,5 @@ func main[] : i64
|
|||||||
for i in 0..1000
|
for i in 0..1000
|
||||||
if i % 5 == 0 || i % 3 == 0
|
if i % 5 == 0 || i % 3 == 0
|
||||||
sum = sum + i
|
sum = sum + i
|
||||||
|
|
||||||
io.println_i64(sum)
|
io.println_i64(sum)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ func main[] : i64
|
|||||||
while true
|
while true
|
||||||
let pkt: net.UDPPacket = net.udp_receive(s, 60000)
|
let pkt: net.UDPPacket = net.udp_receive(s, 60000)
|
||||||
if pkt->size <= 0
|
if pkt->size <= 0
|
||||||
net.udp_free_packet(pkt)
|
net.UDPPacket.free(pkt)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
net.udp_send_to(s, pkt->source_addr, pkt->buffer, pkt->size)
|
net.udp_send_to(s, pkt->source_addr, pkt->buffer, pkt->size)
|
||||||
net.udp_free_packet(pkt)
|
net.UDPPacket.free(pkt)
|
||||||
|
|||||||
@@ -14,7 +14,15 @@ pub struct Analyzer {
|
|||||||
impl Analyzer {
|
impl Analyzer {
|
||||||
pub fn new() -> Analyzer {
|
pub fn new() -> Analyzer {
|
||||||
Analyzer {
|
Analyzer {
|
||||||
functions: HashMap::new(),
|
functions: HashMap::from([
|
||||||
|
("_builtin_heap_head".into(), 0),
|
||||||
|
("_builtin_heap_tail".into(), 0),
|
||||||
|
("_builtin_read64".into(), 1),
|
||||||
|
("_builtin_set64".into(), 2),
|
||||||
|
("_builtin_syscall".into(), -1),
|
||||||
|
("io.printf".into(), -1),
|
||||||
|
("_builtin_environ".into(), 0),
|
||||||
|
]),
|
||||||
constants: HashMap::new(),
|
constants: HashMap::new(),
|
||||||
structs: HashMap::new(),
|
structs: HashMap::new(),
|
||||||
}
|
}
|
||||||
@@ -160,9 +168,7 @@ impl Analyzer {
|
|||||||
args,
|
args,
|
||||||
} => {
|
} => {
|
||||||
if let Expr::Variable(callee_name) = *callee.clone() {
|
if let Expr::Variable(callee_name) = *callee.clone() {
|
||||||
if callee_name.lexeme.starts_with("_builtin_")
|
if self.functions.contains_key(&callee_name.lexeme) {
|
||||||
|| self.functions.contains_key(&callee_name.lexeme)
|
|
||||||
{
|
|
||||||
// its a function (defined/builtin/extern)
|
// its a function (defined/builtin/extern)
|
||||||
if let Some(arity) = self.functions.get(&callee_name.lexeme) {
|
if let Some(arity) = self.functions.get(&callee_name.lexeme) {
|
||||||
if *arity >= 0 && *arity != args.len() as i32 {
|
if *arity >= 0 && *arity != args.len() as i32 {
|
||||||
@@ -171,7 +177,7 @@ impl Analyzer {
|
|||||||
format!("expected {} arguments, got {}", arity, args.len())
|
format!("expected {} arguments, got {}", arity, args.len())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if !callee_name.lexeme.starts_with("_builtin_") {
|
} else {
|
||||||
return error!(
|
return error!(
|
||||||
&paren.loc,
|
&paren.loc,
|
||||||
format!("undefined function: {}", callee_name.lexeme)
|
format!("undefined function: {}", callee_name.lexeme)
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ impl<'a> CodegenX86_64<'a> {
|
|||||||
format!("section .data\n{}{}", self.data_section, self.output)
|
format!("section .data\n{}{}", self.data_section, self.output)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_prologue(&mut self, emit_start: bool) -> Result<(), ZernError> {
|
pub fn emit_prologue(&mut self, use_gcc: bool) -> Result<(), ZernError> {
|
||||||
emit!(
|
emit!(
|
||||||
&mut self.output,
|
&mut self.output,
|
||||||
"section .note.GNU-stack
|
"section .note.GNU-stack
|
||||||
@@ -142,10 +142,25 @@ _builtin_syscall:
|
|||||||
mov r9, [rsp+8]
|
mov r9, [rsp+8]
|
||||||
syscall
|
syscall
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
section .text.io.printf
|
||||||
|
io.printf:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
sub rsp, 48
|
||||||
|
mov [rsp], rsi
|
||||||
|
mov [rsp + 8], rdx
|
||||||
|
mov [rsp + 16], rcx
|
||||||
|
mov [rsp + 24], r8
|
||||||
|
mov [rsp + 32], r9
|
||||||
|
lea rsi, [rsp]
|
||||||
|
call io._printf_impl
|
||||||
|
leave
|
||||||
|
ret
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
if emit_start {
|
if !use_gcc {
|
||||||
emit!(
|
emit!(
|
||||||
&mut self.output,
|
&mut self.output,
|
||||||
"
|
"
|
||||||
@@ -650,9 +665,7 @@ _builtin_environ:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Expr::Variable(callee_name) = &**callee {
|
if let Expr::Variable(callee_name) = &**callee {
|
||||||
if callee_name.lexeme.starts_with("_builtin_")
|
if self.analyzer.functions.contains_key(&callee_name.lexeme) {
|
||||||
|| self.analyzer.functions.contains_key(&callee_name.lexeme)
|
|
||||||
{
|
|
||||||
// its a function (defined/builtin/extern)
|
// its a function (defined/builtin/extern)
|
||||||
emit!(&mut self.output, " call {}", callee_name.lexeme);
|
emit!(&mut self.output, " call {}", callee_name.lexeme);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
22
src/main.rs
22
src/main.rs
@@ -13,6 +13,18 @@ use tokenizer::ZernError;
|
|||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
|
macro_rules! compile_std {
|
||||||
|
($codegen:expr, $( $name:literal ),* $(,)? ) => {
|
||||||
|
$(
|
||||||
|
compile_file_to(
|
||||||
|
$codegen,
|
||||||
|
$name,
|
||||||
|
include_str!(concat!("std/", $name)).into()
|
||||||
|
)?;
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn compile_file_to(
|
fn compile_file_to(
|
||||||
codegen: &mut codegen_x86_64::CodegenX86_64,
|
codegen: &mut codegen_x86_64::CodegenX86_64,
|
||||||
filename: &str,
|
filename: &str,
|
||||||
@@ -63,14 +75,8 @@ fn compile_file(args: Args) -> Result<(), ZernError> {
|
|||||||
|
|
||||||
let mut analyzer = analyzer::Analyzer::new();
|
let mut analyzer = analyzer::Analyzer::new();
|
||||||
let mut codegen = codegen_x86_64::CodegenX86_64::new(&mut analyzer);
|
let mut codegen = codegen_x86_64::CodegenX86_64::new(&mut analyzer);
|
||||||
codegen.emit_prologue(!args.use_gcc)?;
|
codegen.emit_prologue(args.use_gcc)?;
|
||||||
compile_file_to(
|
compile_std!(&mut codegen, "syscalls.zr", "std.zr", "net.zr");
|
||||||
&mut codegen,
|
|
||||||
"syscalls.zr",
|
|
||||||
include_str!("std/syscalls.zr").into(),
|
|
||||||
)?;
|
|
||||||
compile_file_to(&mut codegen, "std.zr", include_str!("std/std.zr").into())?;
|
|
||||||
compile_file_to(&mut codegen, "net.zr", include_str!("std/net.zr").into())?;
|
|
||||||
compile_file_to(&mut codegen, filename, source)?;
|
compile_file_to(&mut codegen, filename, source)?;
|
||||||
|
|
||||||
if !args.output_asm {
|
if !args.output_asm {
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ struct net.UDPSocket
|
|||||||
addr: ptr
|
addr: ptr
|
||||||
|
|
||||||
struct net.UDPPacket
|
struct net.UDPPacket
|
||||||
buffer: ptr
|
data: ptr
|
||||||
source_addr: ptr
|
source_addr: ptr
|
||||||
size: i64
|
size: i64
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ func net.udp_listen[packed_host: i64, port: i64] : net.UDPSocket
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
if _builtin_syscall(SYS_bind, s->fd, s->addr, 16) < 0
|
if _builtin_syscall(SYS_bind, s->fd, s->addr, 16) < 0
|
||||||
net.udp_close_and_free(s)
|
net.UDPSocket.close_and_free(s)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
return s
|
return s
|
||||||
@@ -122,20 +122,92 @@ func net.udp_send_to[s: net.UDPSocket, addr: ptr, data: ptr, size: i64] : void
|
|||||||
|
|
||||||
func net.udp_receive[s: net.UDPSocket, size: i64] : net.UDPPacket
|
func net.udp_receive[s: net.UDPSocket, size: i64] : net.UDPPacket
|
||||||
let pkt: net.UDPPacket = new net.UDPPacket
|
let pkt: net.UDPPacket = new net.UDPPacket
|
||||||
pkt->buffer = mem.alloc(size)
|
pkt->data = mem.alloc(size)
|
||||||
pkt->source_addr = mem.alloc(16)
|
pkt->source_addr = mem.alloc(16)
|
||||||
mem.zero(pkt->source_addr, 16)
|
mem.zero(pkt->source_addr, 16)
|
||||||
|
|
||||||
let addrlen: i64 = 16
|
let addrlen: i64 = 16
|
||||||
pkt->size = _builtin_syscall(SYS_recvfrom, s->fd, pkt->buffer, size, 0, pkt->source_addr, ^addrlen)
|
pkt->size = _builtin_syscall(SYS_recvfrom, s->fd, pkt->data, size, 0, pkt->source_addr, ^addrlen)
|
||||||
return pkt
|
return pkt
|
||||||
|
|
||||||
func net.udp_close_and_free[s: net.UDPSocket] : void
|
func net.UDPSocket.close_and_free[s: net.UDPSocket] : void
|
||||||
_builtin_syscall(SYS_close, s->fd)
|
_builtin_syscall(SYS_close, s->fd)
|
||||||
mem.free(s->addr)
|
mem.free(s->addr)
|
||||||
mem.free(s)
|
mem.free(s)
|
||||||
|
|
||||||
func net.udp_free_packet[pkt: net.UDPPacket] : void
|
func net.UDPPacket.free[pkt: net.UDPPacket] : void
|
||||||
mem.free(pkt->buffer)
|
mem.free(pkt->data)
|
||||||
mem.free(pkt->source_addr)
|
mem.free(pkt->source_addr)
|
||||||
mem.free(pkt)
|
mem.free(pkt)
|
||||||
|
|
||||||
|
const DNS_TYPE_A = 1
|
||||||
|
const DNS_CLASS_IN = 1
|
||||||
|
const DNS_RECURSION_DESIRED = 256
|
||||||
|
|
||||||
|
func net.encode_dns_name[domain: str] : io.Buffer
|
||||||
|
let domain_len: i64 = str.len(domain)
|
||||||
|
let buf: io.Buffer = io.Buffer.alloc(domain_len + 2)
|
||||||
|
let out_pos: i64 = 0
|
||||||
|
let part_start: i64 = 0
|
||||||
|
let i: i64 = 0
|
||||||
|
while i <= domain_len
|
||||||
|
if i == domain_len || domain[i] == '.'
|
||||||
|
let part_len: i64 = i - part_start
|
||||||
|
buf->data[out_pos] = part_len & 0xff
|
||||||
|
out_pos = out_pos + 1
|
||||||
|
mem.copy(domain + part_start, buf->data + out_pos, part_len)
|
||||||
|
out_pos = out_pos + part_len
|
||||||
|
part_start = i + 1
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
buf->data[out_pos] = 0
|
||||||
|
return buf
|
||||||
|
|
||||||
|
func net.build_dns_query[domain_name: str, record_type: i64] : io.Buffer
|
||||||
|
let name: io.Buffer = net.encode_dns_name(domain_name)
|
||||||
|
let out: io.Buffer = io.Buffer.alloc(12 + name->size + 4)
|
||||||
|
|
||||||
|
// header
|
||||||
|
let id: i64 = math.abs(os.urandom_i64() % 65536)
|
||||||
|
mem.write16be(out->data + 0, id)
|
||||||
|
mem.write16be(out->data + 2, DNS_RECURSION_DESIRED)
|
||||||
|
mem.write16be(out->data + 4, 1) // num_questions
|
||||||
|
mem.write16be(out->data + 6, 0) // num_answers
|
||||||
|
mem.write16be(out->data + 8, 0) // num_authorities
|
||||||
|
mem.write16be(out->data + 10, 0) // num_additionals
|
||||||
|
|
||||||
|
// question
|
||||||
|
mem.copy(name->data, out->data + 12, name->size)
|
||||||
|
mem.write16be(out->data + 12 + name->size, record_type)
|
||||||
|
mem.write16be(out->data + 12 + name->size + 2, DNS_CLASS_IN)
|
||||||
|
|
||||||
|
io.Buffer.free(name)
|
||||||
|
return out
|
||||||
|
|
||||||
|
func net.resolve[domain: str] : i64
|
||||||
|
let query: io.Buffer = net.build_dns_query(domain, DNS_TYPE_A)
|
||||||
|
|
||||||
|
// TODO: this probably shouldnt be hardcoded
|
||||||
|
let s: net.UDPSocket = net.create_udp_client(net.pack_addr(8, 8, 8, 8), 53)
|
||||||
|
if s == 0
|
||||||
|
return 0
|
||||||
|
|
||||||
|
net.udp_send_to(s, s->addr, query->data, query->size)
|
||||||
|
io.Buffer.free(query)
|
||||||
|
let pkt: net.UDPPacket = net.udp_receive(s, 1024)
|
||||||
|
net.UDPSocket.close_and_free(s)
|
||||||
|
|
||||||
|
// TODO: do actual parsing
|
||||||
|
|
||||||
|
let pos: i64 = 12 // skip header (12 bytes)
|
||||||
|
|
||||||
|
while pkt->data[pos] != 0
|
||||||
|
pos = pos + pkt->data[pos] + 1 // skip question
|
||||||
|
|
||||||
|
pos = pos + 5 // skip null byte, type(2), class(2)
|
||||||
|
|
||||||
|
pos = pos + 12 // skip name(2), type(2), class(2), ttl(4), rdlength(2)
|
||||||
|
|
||||||
|
let out: i64 = net.pack_addr(pkt->data[pos], pkt->data[pos+1], pkt->data[pos+2], pkt->data[pos+3])
|
||||||
|
net.UDPPacket.free(pkt)
|
||||||
|
return out
|
||||||
|
|||||||
@@ -171,9 +171,15 @@ func mem.read8[x: ptr] : u8
|
|||||||
func mem.read16[x: ptr] : i64
|
func mem.read16[x: ptr] : i64
|
||||||
return x[0] | (x[1] << 8)
|
return x[0] | (x[1] << 8)
|
||||||
|
|
||||||
|
func mem.read16be[x: ptr] : i64
|
||||||
|
return (x[0] << 8) | x[1]
|
||||||
|
|
||||||
func mem.read32[x: ptr] : i64
|
func mem.read32[x: ptr] : i64
|
||||||
return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24)
|
return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24)
|
||||||
|
|
||||||
|
func mem.read32be[x: ptr] : i64
|
||||||
|
return (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3]
|
||||||
|
|
||||||
func mem.read64[x: ptr] : i64
|
func mem.read64[x: ptr] : i64
|
||||||
return _builtin_read64(x)
|
return _builtin_read64(x)
|
||||||
|
|
||||||
@@ -183,9 +189,43 @@ func mem.write32[x: ptr, d: i64] : void
|
|||||||
x[2] = (d >> 16) & 0xff
|
x[2] = (d >> 16) & 0xff
|
||||||
x[3] = (d >> 24) & 0xff
|
x[3] = (d >> 24) & 0xff
|
||||||
|
|
||||||
|
func mem.write16[x: ptr, d: i64] : void
|
||||||
|
x[0] = d & 0xff
|
||||||
|
x[1] = (d >> 8) & 0xff
|
||||||
|
|
||||||
|
func mem.write16be[x: ptr, d: i64] : void
|
||||||
|
x[0] = (d >> 8) & 0xff
|
||||||
|
x[1] = d & 0xff
|
||||||
|
|
||||||
func mem.write64[x: ptr, d: i64] : void
|
func mem.write64[x: ptr, d: i64] : void
|
||||||
_builtin_set64(x, d)
|
_builtin_set64(x, d)
|
||||||
|
|
||||||
|
// see emit_prologue for the io.printf wrapper
|
||||||
|
func io._printf_impl[s: str, args: ptr] : void
|
||||||
|
while s[0]
|
||||||
|
if s[0] == '%'
|
||||||
|
s = s + 1
|
||||||
|
|
||||||
|
if s[0] == 'd'
|
||||||
|
io.print_i64(mem.read64(args))
|
||||||
|
args = args + 8
|
||||||
|
else if s[0] == 'x'
|
||||||
|
io.print_i64_hex(mem.read64(args))
|
||||||
|
args = args + 8
|
||||||
|
else if s[0] == 's'
|
||||||
|
io.print(mem.read64(args))
|
||||||
|
args = args + 8
|
||||||
|
else if s[0] == 'c'
|
||||||
|
io.print_char(mem.read64(args))
|
||||||
|
args = args + 8
|
||||||
|
else if s[0] == '%'
|
||||||
|
io.print_char('%')
|
||||||
|
else if s[0] == 0
|
||||||
|
break
|
||||||
|
else
|
||||||
|
io.print_char(s[0])
|
||||||
|
s = s + 1
|
||||||
|
|
||||||
func io.print_sized[x: str, size: i64] : void
|
func io.print_sized[x: str, size: i64] : void
|
||||||
_builtin_syscall(SYS_write, 1, x, size)
|
_builtin_syscall(SYS_write, 1, x, size)
|
||||||
|
|
||||||
@@ -256,6 +296,16 @@ struct io.Buffer
|
|||||||
data: ptr
|
data: ptr
|
||||||
size: i64
|
size: i64
|
||||||
|
|
||||||
|
func io.Buffer.alloc[size: i64] : io.Buffer
|
||||||
|
let buffer: io.Buffer = new io.Buffer
|
||||||
|
buffer->size = size
|
||||||
|
buffer->data = mem.alloc(size)
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
func io.Buffer.free[buf: io.Buffer] : void
|
||||||
|
mem.free(buf->data)
|
||||||
|
mem.free(buf)
|
||||||
|
|
||||||
func io.read_binary_file[path: str] : io.Buffer
|
func io.read_binary_file[path: str] : io.Buffer
|
||||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
|
|||||||
Reference in New Issue
Block a user