; pexl_lib_conio.asm

; Library functions that can be linked with and imported within pexl code.
; Available functions should:
;  - use global        (so that the linker finds thme)
;  - use PUBLIC_OBJECT (so they don't get free()'d by the refcounter)
;

%include "pexl_rtl.h.asm"

%ifdef OS_WINDOWS

	; For pxo_string_trace
	extern _GetStdHandle@4
	extern _WriteFile@20
	
%endif

;;
;;
;;

; public void pxo_string_trace
; @param pxobj* self
; @return void
PUBLIC_OBJECT
DECLARE_MANGLED pxo_string_trace, 4
	push ebp
	mov ebp, esp
	push ebx
	
	; if (! pxobj->buffer) return;
	mov ebx, dword[ebp+8] 
	cmp dword[ebx], 0
	je .complete
	
%ifdef OS_WINDOWS
	; eax := GetStdHandle(STD_INPUT_HANDLE);
	push dword -11 ; 0xFFFFFFF5
	call _GetStdHandle@4
	
	; WriteFile(stdout, pxobj->buffer, pxobj->strlen, NULL, NULL);
	push 0
	push 0
	push dword[ebx + PXSTRING_OFFSET_STRLEN]
	push dword[ebx + PXSTRING_OFFSET_BUFFER]
	push eax ; stdout
	call _WriteFile@20
	
%elifdef OS_POSIX

	; FIXME:
	; This is a linux-specific syscall, since fwrite kept segfaulting (should
	;   really fix that..)

	push ebx
	push ecx
	push edx ; stash

	; sys_write(stdout, ptr, len)
	mov edx,dword[ebx + PXSTRING_OFFSET_STRLEN]
	mov ecx,dword[ebx + PXSTRING_OFFSET_BUFFER]
	mov ebx, 1
	mov eax, 4 ; magic for sys_write
	int 0x80   ; call kernel
	
	pop edx ; unstash
	pop ecx
	pop ebx
	
%endif
	
.complete:
	pop ebx
	leave
	ret 4 ; one argument

	
	
; public void pxo_putc
; FIXME: no linux implementation?
; @param char
PUBLIC_OBJECT
DECLARE_MANGLED pxo_putc, 4
	push ebp
	mov ebp, esp
	push ebx
	
	mov ebx, ebp
	add ebx, 8 ; ebx = &arg
	
	; As per windows-specific part of pxo_string_trace above
	push dword -11
	call _GetStdHandle@4
	
	push 0
	push 0
	push 1 ; strlen
	push ebx
	push eax
	call _WriteFile@20
	
	pop ebx
	leave
	ret 4 ; one argument