mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
361 lines
6.3 KiB
Plaintext
361 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
|
|
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"
|
|
|