kvisc/ka/command.k

400 lines
7.7 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.
cmdstart:
jmp start
include "crt/crt.k"
CMDCOM_CODE := 0x100000 ; 1MB
CMDCOM_STACK := 0x104000 ; + 16KB
; COMMAND.COM guarantees that programs
; are always loaded on a 16KB boundary
; This is guaranteed to be the case
; in all future versions as well
FILE_LOADP := 0x108000 ; + 32KB
start:
mov rsp, CMDCOM_STACK
mov rbp, zero
call main
mov rax, Sys.EnterHaltMode
trap 0
crash
cmd.versionstr = "COMMAND.COM, version 0.1 (KVISC)\nCopyright (C) 2019, The OS/K Team\nMIT license (permissive), see LICENCE file in source tree"
argbuf.size := 256
argbuf = [argbuf.size]
argv0 = [argbuf.size]
argv1pos = 0
stdin_echoing = 1
prompt = [32]
main:
mov rsi, prompt
mov b[rsi+0], 'C'
mov b[rsi+1], ':'
mov b[rsi+2], '\'
mov b[rsi+3], '>'
mov b[rsi+4], ' '
.print_prompt:
call print, prompt
; empty stuff
call memzero, argbuf, argbuf.size
call memzero, argv0, argbuf.size
nul q[argv1pos]
# call nprint, argv0, argbuf.size
; iterator through argbuf
nul rcx
.input_loop:
pause
pause
pause
; Fill .buf with user input
scan rax
jraxz .input_loop
; ESC key pressed?
beq rax, 0x1B, .handle_EXIT
; backspace character?
bne rax, 8, .handle_input
; anything to delete?
jrcxz .input_loop ; no
; yes, delete it
dec rcx
add rdx, rcx, argbuf
nul b[rdx]
; update screen
bzr b[stdin_echoing], .input_loop
prn 8
jmp .input_loop
.handle_input:
bzr b[stdin_echoing], .se.z
prn rax
.se.z:
beq rax, 10, .extract_argv0
; when max line length is reached,
; force a newline
beq 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
jrcxz .print_prompt
; find first whitespace or null-terminator
mov rcx, argbuf.size
mov rdx, argbuf
scasb rdx, ' '
; argv1 exists? if so, save its position
mov rsi, rdx
.next_space:
mov rcx, b[rsi]
jrcxz .do_extract
; skip spaces
bne rcx, ' ', .not_a_space
inc rsi
jmp .next_space
.not_a_space:
; if we're here, we found a
; non-zero non-space character
mov q[argv1pos], rsi
; fallthrough
.do_extract:
; how much do we copy?
sub rcx, rdx, argbuf
jrcxz .detect_builtin
dec rcx
mov rdi, argbuf
mov rsi, argv0
.copy_loop:
mov b[rsi], b[rdi]
inc rdi
inc rsi
loop .copy_loop
.detect_builtin:
.builtin_cls = "cls"
call strcmp, argv0, .builtin_cls
jraxz .handle_CLS
.builtin_crash = "crash"
call strcmp, argv0, .builtin_crash
jraxz .handle_CRASH
.builtin_date = "date"
call strcmp, argv0, .builtin_date
jraxz .handle_DATE
.builtin_dir = "dir"
call strcmp, argv0, .builtin_dir
jraxz .handle_DIR
.builtin_dump = "dump"
call strcmp, argv0, .builtin_dump
jraxz .handle_DUMP
.builtin_echo = "echo"
call strcmp, argv0, .builtin_echo
jraxz .handle_ECHO
.builtin_erase = "erase"
call strcmp, argv0, .builtin_erase
jraxz .handle_ERASE
.builtin_exit = "exit"
call strcmp, argv0, .builtin_exit
jraxz .handle_EXIT
.builtin_help = "help"
call strcmp, argv0, .builtin_help
jraxz .handle_HELP
.builtin_halt = "halt"
call strcmp, argv0, .builtin_halt
jraxz .handle_HALT
.builtin_make = "make"
call strcmp, argv0, .builtin_make
jraxz .handle_MAKE
.builtin_print = "print"
call strcmp, argv0, .builtin_print
jraxz .handle_PRINT
.builtin_prompt = "prompt"
call strcmp, argv0, .builtin_prompt
jraxz .handle_PROMPT
.builtin_remove = "remove"
call strcmp, argv0, .builtin_remove
jraxz .handle_REMOVE
.builtin_time = "time"
call strcmp, argv0, .builtin_time
jraxz .handle_TIME
.builtin_vers = "vers"
call strcmp, argv0, .builtin_vers
jraxz .handle_VERS
jmp .try_exec
;
; call builtins
;
include "usr/cmd-dir.k"
include "usr/cmd-exec.k"
include "usr/cmd-fsmisc.k"
.handle_CLS:
prn PRN_CLEAR
jmp .print_prompt
.handle_CRASH:
jmp abort
.handle_DATE:
call GetTimeUTC
mov rcx, b[rax+4]
inc rcx
push b[rax+3], rcx, w[rax+6]
call printf, .datefmt
inc rsp, 40
jmp .print_prompt
.datefmt = "%d/%d/%d\n"
.handle_DUMP:
dump
jmp .print_prompt
.handle_ECHO:
mov rax, q[argv1pos]
jraxz .echo.end
call print, rax
.echo.end:
prn 10
jmp .print_prompt
.handle_EXIT:
mov rax, Sys.Shutdown
trap 0
jmp .print_prompt
.handle_HALT:
mov rax, Sys.EnterHaltMode
trap 0
jmp .print_prompt
.handle_PROMPT:
mov ax0, prompt
mov ax1, q[argv1pos]
bzr ax1, .need_params
call strcpy
jmp .print_prompt
.handle_TIME:
call GetTimeUTC
push b[rax], b[rax+1], b[rax+2]
call printf, .timefmt
inc rsp, 24
jmp .print_prompt
.timefmt = "%d:%d:%d\n"
.handle_VERS:
call print, cmd.versionstr
prn 10
jmp .print_prompt
.handle_HELP:
call print, .helpmsg
call print, .helpmsg.cls
call print, .helpmsg.date
call print, .helpmsg.dir
call print, .helpmsg.dump
call print, .helpmsg.echo
call print, .helpmsg.erase
call print, .helpmsg.exit
call print, .helpmsg.help
call print, .helpmsg.halt
call print, .helpmsg.make
call print, .helpmsg.print
call print, .helpmsg.prompt
call print, .helpmsg.remove
call print, .helpmsg.time
call print, .helpmsg.ver
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.dump = " DUMP Toggles debug instruction dumping\n"
.helpmsg.echo = " ECHO Write arguments to standard output\n"
.helpmsg.erase = " ERASE Clear a file, making it blank\n"
.helpmsg.exit = " EXIT Initiate machine shutdown\n"
.helpmsg.help = " HELP Display these messages\n"
.helpmsg.halt = " HALT Put processor in halt mode\n"
.helpmsg.make = " MAKE Create an empty file\n"
.helpmsg.print = " PRINT Display contents of text file\n"
.helpmsg.prompt = " PROMPT Change the command line prompt\n"
.helpmsg.remove = " REMOVE Delete a file (permanently)\n"
.helpmsg.time = " TIME Display current time of day\n"
.helpmsg.ver = " VERS Display current COMMAND.COM version\n"
.exec_not_found:
push argv0
call printf, .enf_errmsg
inc rsp, 8
jmp .print_prompt
.enf_errmsg = "%s: file not found\n"
.file_not_found:
push q[argv1pos], argv0
call printf, .fnf_errmsg
inc rsp, 16
jmp .print_prompt
.fnf_errmsg = "%s: %s: file not found\n"
.empty_file:
push q[argv1pos], argv0
call printf, .ef_errmsg
inc rsp, 16
jmp .print_prompt
.ef_errmsg = "%s: %s: file was empty\n"
.couldnt_open:
push q[argv1pos], argv0
call printf, .cno_errmsg
inc rsp, 16
jmp .print_prompt
.cno_errmsg = "%s: %s: an error occured while opening file\n"
.couldnt_remove:
push q[argv1pos], argv0
call printf, .cne_errmsg
inc rsp, 16
jmp .print_prompt
.cne_errmsg = "%s: %s: an error occured while removing file\n"
.couldnt_read:
push q[argv1pos], argv0
call printf, .cnr_errmsg
inc rsp, 16
jmp .print_prompt
.cnr_errmsg = "%s: %s: an error occured while reading file\n"
.need_params:
call print, argv0
call print, .np_errmsg
jmp .print_prompt
.np_errmsg = ": need more parameters\n"