mirror of
https://github.com/kanaka/mal.git
synced 2024-09-21 10:37:58 +03:00
Added read-string and slurp functions
System calls using Linux 64-bit syscalls in system.asm. Wrapper code in core.asm
This commit is contained in:
parent
cc38947443
commit
cd34fb3b2e
@ -31,6 +31,9 @@ section .data
|
||||
static core_str_symbol, db "str"
|
||||
static core_println_symbol, db "println"
|
||||
|
||||
static core_read_string_symbol, db "read-string"
|
||||
static core_slurp_symbol, db "slurp"
|
||||
|
||||
;; Strings
|
||||
|
||||
static core_emptyp_error_string, db "empty? expects a list, vector or map",10
|
||||
@ -90,6 +93,9 @@ core_environment:
|
||||
core_env_native core_str_symbol, core_str
|
||||
core_env_native core_println_symbol, core_println
|
||||
|
||||
core_env_native core_read_string_symbol, core_read_string
|
||||
core_env_native core_slurp_symbol, core_slurp
|
||||
|
||||
; -----------------
|
||||
; Put the environment in RAX
|
||||
mov rax, rsi
|
||||
@ -562,3 +568,48 @@ core_prn_functions:
|
||||
call alloc_cons
|
||||
mov [rax], BYTE maltype_nil
|
||||
ret
|
||||
|
||||
;; Given a string, calls read_str to get an AST
|
||||
core_read_string:
|
||||
mov al, BYTE [rsi]
|
||||
mov ah, al
|
||||
and ah, content_mask
|
||||
cmp ah, content_pointer
|
||||
jne .no_string
|
||||
|
||||
mov rsi, [rsi + Cons.car]
|
||||
mov al, BYTE [rsi]
|
||||
cmp al, maltype_string
|
||||
jne .no_string
|
||||
|
||||
call read_str
|
||||
ret
|
||||
|
||||
.no_string:
|
||||
; Didn't get a string input
|
||||
call alloc_cons
|
||||
mov [rax], BYTE maltype_nil
|
||||
ret
|
||||
|
||||
|
||||
;; Reads a file into a string
|
||||
core_slurp:
|
||||
mov al, BYTE [rsi]
|
||||
mov ah, al
|
||||
and ah, content_mask
|
||||
cmp ah, content_pointer
|
||||
jne .no_string
|
||||
|
||||
mov rsi, [rsi + Cons.car]
|
||||
mov al, BYTE [rsi]
|
||||
cmp al, maltype_string
|
||||
jne .no_string
|
||||
|
||||
call read_file
|
||||
ret
|
||||
|
||||
.no_string:
|
||||
; Didn't get a string input
|
||||
call alloc_cons
|
||||
mov [rax], BYTE maltype_nil
|
||||
ret
|
||||
|
113
nasm/system.asm
113
nasm/system.asm
@ -3,6 +3,11 @@
|
||||
;;; This file contains system-specific functions,
|
||||
;;; which use calls to the operating system (Linux)
|
||||
|
||||
section .data
|
||||
static error_open_file_string, db "Error opening file "
|
||||
static error_read_file_string, db "Error reading file "
|
||||
|
||||
section .text
|
||||
|
||||
;; -------------------------------------------
|
||||
;; Prints a raw string to stdout
|
||||
@ -91,3 +96,111 @@ read_line:
|
||||
pop rax ; Restore pointer to string
|
||||
mov DWORD [rax + Array.length], ebx ; Set string length
|
||||
ret
|
||||
|
||||
;; Reads a file into a string
|
||||
;;
|
||||
;; Input: RSI - File name string (char Array)
|
||||
;;
|
||||
;; Returns: string in RAX
|
||||
;;
|
||||
;; Pieces from https://stackoverflow.com/questions/20133698/how-to-read-from-and-write-to-files-using-nasm-for-x86-64bit
|
||||
read_file:
|
||||
|
||||
mov rdi, rsi ; Filename
|
||||
|
||||
; Need to add null terminator
|
||||
mov eax, DWORD [rdi + Array.length]
|
||||
cmp eax, (array_chunk_len * 8)
|
||||
je .error_filename ; File name too long
|
||||
|
||||
; Insert a null terminator
|
||||
add rax, rdi
|
||||
mov [rax + Array.data], BYTE 0
|
||||
|
||||
; Open the file
|
||||
mov rax, 2
|
||||
add rdi, Array.data; filename in RDI
|
||||
xor rsi, rsi ; O_RDONLY in RSI
|
||||
syscall
|
||||
|
||||
; Check for error (return -1)
|
||||
cmp eax, 0
|
||||
jl .error_open
|
||||
|
||||
mov rdi, rax ; File handle in RDI
|
||||
|
||||
; Create a string
|
||||
push rdi
|
||||
call string_new ; In RAX
|
||||
pop rdi
|
||||
|
||||
mov r9, rax ; Current Array
|
||||
push rax ; This is popped in .done
|
||||
.loop:
|
||||
; Read next chunk
|
||||
push r9
|
||||
|
||||
mov rsi, r9
|
||||
add rsi, Array.data ; address
|
||||
|
||||
mov rax, 0 ; sys_read
|
||||
; file handle in RDI
|
||||
mov rdx, (array_chunk_len * 8) ; count
|
||||
syscall
|
||||
|
||||
pop r9
|
||||
|
||||
; Characters read in RAX
|
||||
|
||||
cmp rax, 0
|
||||
jl .error_read
|
||||
|
||||
cmp rax, (array_chunk_len * 8)
|
||||
jg .error_read
|
||||
|
||||
mov [r9 + Array.length], DWORD eax
|
||||
|
||||
jl .done
|
||||
|
||||
; May still be more to read.
|
||||
; Allocate another
|
||||
call string_new
|
||||
mov [r9 + Array.next], rax
|
||||
mov r9, rax
|
||||
jmp .loop
|
||||
|
||||
.done:
|
||||
; Close the file
|
||||
mov rax, 3
|
||||
;rdi = file handle
|
||||
syscall
|
||||
|
||||
pop rax
|
||||
ret
|
||||
|
||||
.error_filename:
|
||||
.error_open:
|
||||
; File name in RDI
|
||||
sub rdi, Array.data
|
||||
|
||||
; Make the error message
|
||||
mov rsi, error_open_file_string
|
||||
mov edx, error_open_file_string.len
|
||||
call raw_to_string
|
||||
mov rsi, rax
|
||||
mov cl, 39 ; (')
|
||||
call string_append_char
|
||||
mov rdx, rdi ; file name
|
||||
call string_append_string
|
||||
mov cl, 39
|
||||
call string_append_char
|
||||
|
||||
; Error message in RSI
|
||||
jmp error_throw
|
||||
|
||||
.error_read:
|
||||
mov rsi, error_read_file_string
|
||||
mov edx, error_read_file_string.len
|
||||
call raw_to_string
|
||||
mov rsi, rax
|
||||
jmp error_throw
|
||||
|
@ -387,8 +387,12 @@ incref_object:
|
||||
|
||||
;; -------------------------------------------
|
||||
;; String type
|
||||
|
||||
;;
|
||||
;; Create a new string, address in RAX
|
||||
;;
|
||||
;; Modifies registers
|
||||
;; RBX
|
||||
;;
|
||||
string_new:
|
||||
call alloc_array
|
||||
mov [rax], BYTE maltype_string
|
||||
|
Loading…
Reference in New Issue
Block a user