;;; Dynamic memory management. Allocated with MALLOC and released with
;;; MUNMAP (see below)
- ;; ( size -- addr )
- ;; Allocates memory (using brk)
WORD p_malloc,'MALLOC',fasm
+ ;; ( size -- addr )
+ ;; Allocates memory (using mmap)
pushr rsi ; pretend it's a FORTH word since it
; ends via sys_mmap_asm
pop rax
push qword 0 ; offset
jmp sys_mmap_asm ; exit via sys_mmap
+ WORD p_realloc,'REALLOC',fasm
+ ;; ( addr old new -- )
+ ;; Try remapping a given MMAP region of old size to a new size
+ ;; mremap(void *old_address, size_t old_size,
+ ;; size_t new_size, int flags, ... /* void *new_address */);
+ pushr rsi
+ push 1 ; MREMAP_MAYMOVE
+ jmp sys_mmap_asm ; exit via sys_mmap
+
;;; ========================================
;;; Input stream handling.
;;;
;;; * block address
;;; * -1
;;; * size of block
-;;; * current read position (starts at 8 = after block size)
+;;; * current read position
WORD p_stream,'STREAM',fasm
;; ( fd size -- addr ) or ( block -1 -- addr )
mov rbx,qword [rax+16] ; copy fill
mov qword [rax+24],rbx ; into current
next
-
+
+ WORD p_stream_nchars,'STREAM-NCHARS',fasm
+ ;; ( stream -- n )
+ ;; Scan over whitespace in the stream buffer (without actually
+ ;; consuming) and tell how much then remains.
+ pushr rsi
+ mov rcx,qword [rsp]
+ mov rbx,qword [rcx+16] ; fill
+ sub rbx,qword [rcx+24] ; current
+ cmp qword [rcx+8],-1
+ je p_stream_nchars_memblock
+ mov rsi,rcx
+ add rsi,32
+ jmp p_stream_nchars_skipblanks
+p_stream_nchars_memblock:
+ mov rsi,qword [rcx]
+p_stream_nchars_skipblanks:
+ add rsi,qword [rcx+24] ;
+ cmp rbx,0
+ je p_stream_nchars_done
+p_stream_nchars_loop:
+ lodsb
+ cmp al,32
+ jg p_stream_nchars_done
+ dec rbx
+ jg p_stream_nchars_loop
+p_stream_nchars_done:
+ mov qword [rsp],rbx
+ popr rsi
+ next
+
;;; ========================================
;;; Stream reading
;;; READ-STREAM-CHAR ( stream -- ch )
;; ( stream -- ch )
pushr rsi
mov rax,qword [rsp]
- mov rbx,[rax+16] ; fill
+ mov rbx,qword [rax+16] ; fill
p_read_stream_char.READ:
- mov rcx,[rax+24] ; current
+ mov rcx,qword [rax+24] ; current
cmp rbx,rcx
jg p_read_stream_char.CHAR
popr rsi
next
+ WORD p_double_quote,'"',fasm ;; " (fool emacs)
+ ;; ( -- char* n )
+ ;; Scan to double quote in stream buffer, putting the string on PAD
+ pushr rsi
+ push p_pad_DFA
+ push 0
+p_double_quote_loop:
+ DOFORTH p_input, p_get, p_read_stream_char
+ pop rax
+ cmp rax,0
+ jl p_double_quote_endstream
+ cmp rax,'"' ; " (fool emacs)
+ je p_double_quote_endquote
+ lea rdi,[p_pad_DFA]
+ add rdi,qword [rsp]
+ stosb
+ inc qword [rsp]
+ jmp p_double_quote_loop
+p_double_quote_endquote:
+p_double_quote_endstream:
+ popr rsi
+ next
+
WORD p_tell,'TELL',fasm
;; ( chars* n -- )
;; Write n bytes from chars* to stdout
popr rsi
next
-p_emit_buffer: dq 0
-
WORD p_emit,'EMIT',fasm
;; ( c -- )
;; Write byte to stdout
pushr rsi
- pop rax
- mov [p_emit_buffer],al
+ mov rax,rsp
push 1
- push p_emit_buffer
+ push rax
push 1
DOFORTH sys_write
- pop rax
+ pop rax ; ignore return value
+ pop rax ; drop input data
popr rsi
next
WORD p_sp,'SP',dovalue
;; ( -- c )
;; Pushes a space character on the stack
- dq 10
-
+ dq 32
+
+ WORD p_digits,'DIGITS',dovariable
+ db '0123456789abcdef'
+
+ WORD p_dot,'.',fasm
+ ;; ( v -- )
+ ;; Print TOP value as unsigned BASE integer
+ pushr rsi
+ mov rax,qword [rsp]
+ cmp rax,0
+ jge p_dot_positive
+ cmp qword [p_base_DFA],10
+ jne p_dot_positive
+ push '-'
+ DOFORTH p_emit
+ mov rax,qword [rsp]
+ neg rax
+p_dot_positive:
+ xor rdx,rdx
+ div qword [p_base_DFA] ; rdx:rax / BASE => q=rax, r=rdx
+ mov qword [rsp],rdx
+ cmp rax,0
+ je p_dot_remainder
+ push rax
+ DOFORTH p_dot
+p_dot_remainder:
+ pop rdx
+ xor rax,rax
+ mov al,[p_digits_DFA+rdx]
+ push rax
+ DOFORTH p_emit
+ popr rsi
+ next