kvisc/ka/command.k

400 lines
7.8 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"
#define CMDCOM_CODE 0x100000 // 1MB
#define 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 veesions as well
#define FILE_LOADP 0x108000 // + 32KB
start:
mov esp, CMDCOM_STACK
mov ebp, zero
call main
mov eax, Sys.EnterHaltMode
trap 0
crash
cmd.veesionstr = "COMMAND.COM, veesion 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 esi, prompt
mov b[esi+0], 'C'
mov b[esi+1], ':'
mov b[esi+2], '\'
mov b[esi+3], '>'
mov b[esi+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 ecx
.input_loop:
pause
pause
pause
; Fill .buf with user input
scan eax
jeaxz .input_loop
; ESC key pressed?
beq eax, 0x1B, .handle_EXIT
; backspace character?
bne eax, 8, .handle_input
; anything to delete?
jecxz .input_loop ; no
; yes, delete it
dec ecx
add edx, ecx, argbuf
nul b[edx]
; update screen
bzr b[stdin_echoing], .input_loop
prn 8
jmp .input_loop
.handle_input:
bzr b[stdin_echoing], .se.z
prn eax
.se.z:
beq eax, 10, .extract_argv0
; when max line length is reached,
; force a newline
beq ecx, argbuf.size, .extract_argv0
; add character to buffer and increase iterator (ecx)
add edx, ecx, argbuf
mov b[edx], eax
inc ecx
; another one
jmp .input_loop
.extract_argv0:
; did we read anything at all?
; if not, just go back to waiting input
jecxz .print_prompt
; find first whitespace or null-terminator
mov ecx, argbuf.size
mov edx, argbuf
scasb edx, ' '
; argv1 exists? if so, save its position
mov esi, edx
.next_space:
mov ecx, b[esi]
jecxz .do_extract
; skip spaces
bne ecx, ' ', .not_a_space
inc esi
jmp .next_space
.not_a_space:
; if we're here, we found a
; non-zero non-space character
mov q[argv1pos], esi
; fallthrough
.do_extract:
; how much do we copy?
sub ecx, edx, argbuf
jecxz .detect_builtin
dec ecx
mov edi, argbuf
mov esi, argv0
.copy_loop:
mov b[esi], b[edi]
inc edi
inc esi
loop .copy_loop
.detect_builtin:
.builtin_cls = "cls"
call strcmp, argv0, .builtin_cls
jeaxz .handle_CLS
.builtin_crash = "crash"
call strcmp, argv0, .builtin_crash
jeaxz .handle_CRASH
.builtin_date = "date"
call strcmp, argv0, .builtin_date
jeaxz .handle_DATE
.builtin_dir = "dir"
call strcmp, argv0, .builtin_dir
jeaxz .handle_DIR
.builtin_dump = "dump"
call strcmp, argv0, .builtin_dump
jeaxz .handle_DUMP
.builtin_echo = "echo"
call strcmp, argv0, .builtin_echo
jeaxz .handle_ECHO
.builtin_erase = "erase"
call strcmp, argv0, .builtin_erase
jeaxz .handle_ERASE
.builtin_exit = "exit"
call strcmp, argv0, .builtin_exit
jeaxz .handle_EXIT
.builtin_help = "help"
call strcmp, argv0, .builtin_help
jeaxz .handle_HELP
.builtin_halt = "halt"
call strcmp, argv0, .builtin_halt
jeaxz .handle_HALT
.builtin_make = "make"
call strcmp, argv0, .builtin_make
jeaxz .handle_MAKE
.builtin_print = "print"
call strcmp, argv0, .builtin_print
jeaxz .handle_PRINT
.builtin_prompt = "prompt"
call strcmp, argv0, .builtin_prompt
jeaxz .handle_PROMPT
.builtin_remove = "remove"
call strcmp, argv0, .builtin_remove
jeaxz .handle_REMOVE
.builtin_time = "time"
call strcmp, argv0, .builtin_time
jeaxz .handle_TIME
.builtin_vers = "vers"
call strcmp, argv0, .builtin_vers
jeaxz .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 ecx, b[eax+4]
inc ecx
push b[eax+3], ecx, w[eax+6]
call printf, .datefmt
add esp, 40
jmp .print_prompt
.datefmt = "%d/%d/%d\n"
.handle_DUMP:
dump
jmp .print_prompt
.handle_ECHO:
mov eax, q[argv1pos]
jeaxz .echo.end
call print, eax
.echo.end:
prn 10
jmp .print_prompt
.handle_EXIT:
mov eax, Sys.Shutdown
trap 0
jmp .print_prompt
.handle_HALT:
mov eax, 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[eax], b[eax+1], b[eax+2]
call printf, .timefmt
add esp, 24
jmp .print_prompt
.timefmt = "%d:%d:%d\n"
.handle_VERS:
call print, cmd.veesionstr
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 veesion\n"
.exec_not_found:
push argv0
call printf, .enf_errmsg
add esp, 8
jmp .print_prompt
.enf_errmsg = "%s: file not found\n"
.file_not_found:
push q[argv1pos], argv0
call printf, .fnf_errmsg
add esp, 16
jmp .print_prompt
.fnf_errmsg = "%s: %s: file not found\n"
.empty_file:
push q[argv1pos], argv0
call printf, .ef_errmsg
add esp, 16
jmp .print_prompt
.ef_errmsg = "%s: %s: file was empty\n"
.couldnt_open:
push q[argv1pos], argv0
call printf, .cno_errmsg
add esp, 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
add esp, 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
add esp, 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"