1
1
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:
Ben Dudson 2017-11-11 23:33:58 +00:00
parent cc38947443
commit cd34fb3b2e
3 changed files with 169 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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