kvisc/ka/usr/cmd/main.k

360 lines
6.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
mov q[argv1pos], 0
.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 r10, b[r11]
b.z r10, 0, .no_argv1
; skip spaces
cmp r10, ' '
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_date = "date"
mov ax0, argv0
mov ax1, .builtin_date
call strcmp
b.z rax, 0, .handle_DATE
.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_time = "time"
mov ax0, argv0
mov ax1, .builtin_time
call strcmp
b.z rax, 0, .handle_TIME
.builtin_ver = "ver"
mov ax0, argv0
mov ax1, .builtin_ver
call strcmp
b.z rax, 0, .handle_VER
jmp .command_not_found
;
; call builtins
;
.handle_CLS:
prn 0xC15000AF
jmp .print_prompt
.handle_DATE:
time ax0
call GetTimeUTC
push b[rax+3]
mov rcx, b[rax+4]
inc rcx
push rcx
push w[rax+6]
mov ax0, .datefmt
call printf
add rsp, 5*8
jmp .print_prompt
.datefmt = "%d/%d/%d\n"
.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:
mov rax, Sys.OpenFile
mov ax0, q[argv1pos]
b.z ax0, 0, .need_params
trap 0
b.l rax, 0, .file_not_found
mov ax0, rax
mov ax1, FILE_LOADP
mov ax2, FILE_MAXSZ
mov rax, Sys.ReadFile
trap 0
mov rcx, rax
mov rax, Sys.CloseFile
trap 0
b.l rax, 0, .couldnt_read
b.z rax, 0, .empty_file
mov rdx, FILE_LOADP
prns.rep rdx
jmp .print_prompt
.handle_TIME:
time ax0
call GetTimeUTC
push b[rax]
push b[rax+1]
push b[rax+2]
mov ax0, .timefmt
call printf
add rsp, 3*8
jmp .print_prompt
.timefmt = "%d:%d:%d\n"
.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.date
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.time
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.date = " DATE Display current date\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 Display these messages\n"
.helpmsg.print = " PRINT Display contents of text file\n"
.helpmsg.time = " TIME Display current time of day\n"
.helpmsg.ver = " VER Display current COMMAND.COM and DOS kernel versions\n"
.command_not_found:
mov rcx, STRLEN_MAX
mov rdx, argv0
prns.rep.nz rdx
mov rdx, .cnf_errmsg
prns.rep.nz rdx
jmp .print_prompt
.cnf_errmsg = ": command not found\n"
.file_not_found:
mov ax0, .fnf_errmsg
push q[argv1pos]
push argv0
call printf
add rsp, 16
jmp .print_prompt
.fnf_errmsg = "%s: %s: file not found\n"
.empty_file:
mov ax0, .ef_errmsg
push q[argv1pos]
push argv0
call printf
add rsp, 16
jmp .print_prompt
.ef_errmsg = "%s: %s: file is empty\n"
.couldnt_read:
mov ax0, .cno_errmsg
push q[argv1pos]
push argv0
call printf
add rsp, 16
jmp .print_prompt
.cno_errmsg = "%s: %s: an error occured while reading file\n"
.need_params:
mov rcx, STRLEN_MAX
mov rdx, argv0
prns.rep.nz rdx
mov rdx, .np_errmsg
prns.rep.nz rdx
jmp .print_prompt
.np_errmsg = ": need more parameters\n"