kvisc/ka/usr/cmd/main.k

240 lines
4.3 KiB
Plaintext

; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
argbuf.size := 256
argbuf = [argbuf.size]
argv0 = [argbuf.size]
argv1pos = 0
stdin_echoing = 1
ps1 = "C:\\> "
main:
.print_prompt:
mov rcx, STRLEN_MAX
mov rdx, ps1
prns.rep.nz rdx
; empty argbuf
mov rcx, argbuf.size
mov rdx, argbuf
stosb.rep rdx, 0
; iterator through argbuf
xor rcx, rcx
.input_loop:
pause
pause
; Fill .buf with user input
scan rax
b.z rax, 0, .input_loop
; backspace character?
b.nz rax, 8, .handle_input
; anything to delete?
b.z rcx, 0, .input_loop
; delete it
dec rcx
add rdx, rcx, argbuf
mov b[rdx], 0
; update screen
cmp b[stdin_echoing], 1
prn.z 8
jmp .input_loop
.handle_input:
cmp b[stdin_echoing], 1
prn.z rax
b.z rax, 10, .extract_argv0
; when max line length is reached,
; force a newline
b.z rcx, argbuf.size, .extract_argv0
; add character to buffer and increase iterator (rcx)
add rdx, rcx, argbuf
mov b[rdx], rax
inc rcx
; another one
jmp .input_loop
.extract_argv0:
; did we read anything at all?
; if not, just go back to waiting input
b.z rcx, 0, .print_prompt
; find first whitespace or null-terminator
mov rcx, argbuf.size
mov rdx, argbuf
scasb.rep.nz rdx, ' '
; argv1 exists? if so, save its position
mov r11, rdx
b.z b[r11], 0, .no_argv1
inc r11
.next_space:
mov rx8, b[r11]
b.z rx8, 0, .no_argv1
; skip spaces
cmp rx8, ' '
inc.z r11
jmp.z .next_space
mov q[argv1pos], r11
; fallthrough
.no_argv1:
; empty argv0
mov rcx, argbuf.size
mov rax, argv0
stosb.rep rax, 0
; extract argv0
sub rcx, rdx, argbuf
mov rdx, argbuf
mov rax, argv0
movsb.rep rax, rdx
.detect_builtin:
.builtin_cls = "cls"
mov ax0, argv0
mov ax1, .builtin_cls
call strcmp
b.z rax, 0, .handle_CLS
.builtin_dir = "dir"
mov ax0, argv0
mov ax1, .builtin_dir
call strcmp
b.z rax, 0, .handle_DIR
.builtin_echo = "echo"
mov ax0, argv0
mov ax1, .builtin_echo
call strcmp
b.z rax, 0, .handle_ECHO
.builtin_exit = "exit"
mov ax0, argv0
mov ax1, .builtin_exit
call strcmp
b.z rax, 0, .handle_EXIT
.builtin_help = "help"
mov ax0, argv0
mov ax1, .builtin_help
call strcmp
b.z rax, 0, .handle_HELP
.builtin_print = "print"
mov ax0, argv0
mov ax1, .builtin_print
call strcmp
b.z rax, 0, .handle_PRINT
.builtin_ver = "ver"
mov ax0, argv0
mov ax1, .builtin_ver
call strcmp
b.z rax, 0, .handle_VER
; fallthrough
.exec_prog:
; fallthrough
.not_found:
mov rcx, STRLEN_MAX
mov rdx, argv0
prns.rep.nz rdx
mov rdx, .errmsg
prns.rep.nz rdx
jmp .print_prompt
.errmsg = " : command not found\n"
;
; call builtins
;
.handle_CLS:
prn 0xC15000AF
jmp .print_prompt
.handle_DIR:
call builtins.dir
jmp .print_prompt
.handle_ECHO:
mov rdx, q[argv1pos]
b.z rdx, 0, .echo.end
mov rcx, argbuf.size
prns.rep.nz rdx
.echo.end:
prn 10
jmp .print_prompt
.handle_EXIT:
mov rax, Sys.Shutdown
trap 0
.handle_PRINT:
jmp .print_prompt
.handle_VER:
mov rcx, STRLEN_MAX
mov rdx, cmd.versionstr
prns.rep.nz rdx
prn 10
jmp .print_prompt
.handle_HELP:
mov rcx, STRLEN_MAX
mov rdx, .helpmsg
prns.rep.nz rdx
mov rdx, .helpmsg.cls
prns.rep.nz rdx
mov rdx, .helpmsg.dir
prns.rep.nz rdx
mov rdx, .helpmsg.echo
prns.rep.nz rdx
mov rdx, .helpmsg.exit
prns.rep.nz rdx
mov rdx, .helpmsg.help
prns.rep.nz rdx
mov rdx, .helpmsg.print
prns.rep.nz rdx
mov rdx, .helpmsg.ver
prns.rep.nz rdx
jmp .print_prompt
.helpmsg = "The following commands are built-in:\n"
.helpmsg.cls = " CLS Clear screen\n"
.helpmsg.dir = " DIR Print contents of current directory\n"
.helpmsg.echo = " ECHO Write arguments to standard output\n"
.helpmsg.exit = " EXIT Initiate machine shutdown\n"
.helpmsg.help = " HELP Show these messages\n"
.helpmsg.print = " PRINT Show contents of text file\n"
.helpmsg.ver = " VER Show current COMMAND.COM and DOS kernel versions\n"