section .text
	global _start

_start:
	; TODO: handle interrupt signal

	push rbp
	mov rbp, rsp
	sub rsp, 0x110
	mov r15, rsp
	sub rsp, 0x110
	mov r9, rsp
	sub rsp, 0x110
	mov rbx, rsp

	mov rax, 0x1
	mov rdi, 0x1
	mov rsi, msg
	mov rdx, 0x1b
	syscall

	jmp parse_path

rloop:
	mov rax, 0x1
	mov rdi, 0x1
	mov rsi, prompt
	mov rdx, 0xd
	syscall

	mov r8, -0x1
	mov r12, rloopr
	jmp bzero

rloopr:
	mov rax, 0x0
	mov rdi, 0x0
	mov rsi, r15
	mov rdx, 0xff
	syscall

	; check for quit
	cmp byte [r15], 0x0
	mov r12, quit
	je weol

	; call parse
	jmp parse

exec:
	; fork so we don't hurt ourselves
	mov rax, 0x39
	syscall
	mov dword [cpid], eax
	cmp dword [cpid], 0x0
	jne wait4_it

	; now that we know what to execute, do so
	mov rax, 0x3b
	mov rdi, r13
	mov rsi, r14
	mov rdx, 0x0
	syscall

	; and now kill the child process
	jmp quit

wait4_it:
	mov rdi, rax
	mov rax, 0x3d
	xor rsi, rsi ; null status pointer
	xor rdx, rdx
	xor rcx, rcx ; null rusage pointer
	syscall

	mov dword [cpid], -0x1
	jmp rloop

; input: none
; output: r9 (path elements), r10 (length)
; clobbered: r8, r12
; other: r15 (buffer)
parse_path:
	mov rax, 0x2
	mov rdi, env
	mov rsi, 0x0
	syscall
	cmp rax, 0x0
	jl quit

	mov r8, -0x1
	mov r12, parse_path2
	jmp bzero

parse_path2:
	mov rdi, rax
	mov rax, 0x0
	mov rsi, r9
	mov rdx, 0xff
	syscall
	cmp rax, 0x0
	jl quit
	mov r8, r9
	dec r8

pathfinder:
	inc r8
	xor rax, rax
	mov byte al, [r8]
	cmp al, 0x50
	jne pathfinder
	mov byte al, [r8+1]
	cmp al, 0x41
	jne pathfinder
	mov byte al, [r8+2]
	cmp al, 0x54
	jne pathfinder
	mov byte al, [r8+3]
	cmp al, 0x48
	jne pathfinder
	mov byte al, [r8+4]
	cmp al, 0x3d
	jne pathfinder
	mov byte al, [r8+5]
	cmp al, 0x22
	jne pathfinder
	cmp al, 0x0
	je quit
	add r8, 0x6
	mov r10, 0x1
	push 0x0
	push r8
	dec r8

pathender:
	inc r8
	mov al, [r8]
	cmp al, 0x3a
	je pathender1
	cmp al, 0x22
	jne pathender
	mov byte [r8], 0x0
	mov r9, rsp
	jmp rloop

pathender1:
	inc r10
	mov byte [r8], 0x0
	lea rcx, [r8+0x1]
	push rcx
	jmp pathender

;input: r8 (iterator), r15 (buffer), r12 (return address)
;output: none
bzero:
	inc r8
	mov byte [r8+r15], 0x0
	cmp r8, 0xff
	jle bzero
	jmp r12

;input: r15 (buffer)
;output: r13 (path), r14 (arguments)
;clobbered: r8, rax, rbx, rcx
parse: ; needs special commands: cd exit export echo eval pwd
	;also needs pipes (|, >, <)
	push 0x0
	xor r13, r13
	jmp strlen

; go through and sub/push
parse1:
	cmp byte [r8+r15], 0x20
	je subzp
	cmp byte [r8+r15], 0x0a
	je subz
	cmp byte [r8+r15], 0x2f
	je sabsf
	cmp byte [r8+r15], 0x2e
	je sabsf

parse1r:
	dec r8
	cmp r8, 0x0
	jl parse2
	jmp parse1

sabsf:
	cmp r8, 0x1
	jg parse1r
	mov r13, 0x1
	jmp parse1r

subz:
	mov byte [r8+r15], 0x0
	jmp parse1

subzp:
	mov byte [r8+r15], 0x0
	lea rax, [r8+r15+0x1]
	push rax
	jmp parse1

parse2:
	push rbx
	mov r14, rsp
	cmp r13, 0x0
	jg parse7
	mov r8, -0x1

parse3:
	inc r8
	cmp r8, r10
	je parse4
	mov r13, r15
	mov rcx, [r9+r8*8]
	push r8
	jmp concat

parse4: ; not found
	mov rax, 0x1
	mov rdi, 0x1
	mov rsi, nfe
	mov rdx, 0x1a
	syscall
	jmp rloop

parse5: ; test rbx
	pop r8

	mov rax, 0x2
	mov rdi, rbx
	xor rsi, rsi
	xor rdx, rdx
	syscall

	cmp rax, 0x0
	jl parse3
	
	mov rdi, rax
	mov rax, 0x3
	syscall

parse6: ; found it
	mov r13, rbx
	jmp exec

parse7: ; absolute path
	mov rax, 0x2
	mov rdi, r15
	xor rsi, rsi
	xor rdx, rdx
	syscall

	cmp rax, 0x0
	jl parse4

	mov rdi, rax
	mov rax, 0x3
	syscall

	mov r13, r15
	jmp exec
	

;input: r12 (return address), r15 (buffer)
;output: r8 (length)
strlen:
	xor r8, r8

strlen1:
	cmp byte [r8+r15], 0x0
	je parse1
	cmp byte [r8+r15], 0xa
	je parse1
	inc r8
	jmp strlen1

; input: rcx (a), r13 (b)
; output: rbx (string)
; clobbered: r8, r11
concat:
	mov r8, -0x1
	jmp jlen1

jlen1:
	inc r8
	cmp byte [r8+rcx], 0x0
	je jlen02
	cmp byte [r8+rcx], 0xa
	je jlen02
	jmp jlen1

jlen02:
	dec r8
	mov r11, -0x1

jlen2:
	inc r8
	inc r11
	cmp byte [r11+r13], 0x0
	je treg
	cmp byte [r11+r13], 0xa
	je treg
	jmp jlen2

treg:
	cmp r8, 0xff
	jg boe
	xchg r15, rbx
	mov r8, -0x1
	mov r12, rsinc
	jmp bzero

rsinc:
	xchg r15, rbx
	mov r8, -0x1
	mov r11, -0x1

join1:
	inc r8
	cmp byte [r8+rcx], 0x0
	je join02
	cmp byte [r8+rcx], 0xa
	je join02
	mov al, [r8+rcx]
	mov [r8+rbx], al
	jmp join1

join02:
	mov byte [r8+rbx], 0x2f
join2:
	inc r8
	inc r11
	cmp byte [r11+r13], 0x0
	je parse5
	cmp byte [r11+r13], 0xa
	je parse5
	mov al, [r11+r13]
	mov [r8+rbx], al
	jmp join2

boe:
	mov rax, 0x1
	mov rdi, 0x1
	mov rsi, boem
	mov rdx, 0x1f
	jmp quit

; interrupt signal handler
sigint:
	cmp dword [cpid], 0x0
	jl sigint_nc

sigint_c: ; kill the child
	mov rax, 0x3e
	mov rdi, [cpid]
	mov rsi, 0x2
	syscall

sigint_nc:
	mov r12, rloop
	jmp weol

; input: r12 (return address)
; output: none
weol:
	mov rax, 0x1
	mov rdi, 0x1
	mov rsi, eol
	mov rdx, 0x1
	syscall
	jmp r12

quit:
	mov rax, 0x3c
	mov rdi, 0x0
	syscall

section .data
	sigs: dd 0x2
	cpid: dd 0x0
	eol: db 0xa
	msg: db "Welcome to deadbeef shell", 0x21, 0x0a
	prompt: db "[0xdeadbeef]", 0x20
	nfe: db "Error: program not found", 0x2e, 0x0a
	env: db "/etc/environment", 0x0
	boem: db "Error: input overflows buffer", 0x2e, 0x0a
