kvisc/ka/usr/cmd/main.k

388 lines
7.2 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
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 argbuf
mov rcx, argbuf.size
mov rdx, argbuf
stosb.rep rdx, zero
; iterator through argbuf
mov rcx, zero
mov q[argv1pos], zero
.input_loop:
pause
pause
pause
; Fill .buf with user input
scan rax
jmp.axz .input_loop
; backspace character?
b.nz rax, 8, .handle_input
; anything to delete?
jmp.cxz .input_loop ; no
; yes, delete it
dec rcx, 1
add rdx, rcx, argbuf
mov b[rdx], zero
; 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, 1
; another one
jmp .input_loop
.extract_argv0:
; did we read anything at all?
; if not, just go back to waiting input
jmp.cxz .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 rsi, rdx
.next_space:
mov rcx, b[rsi]
jmp.cxz .do_extract
; skip spaces
cmp rcx, ' '
inc.z rsi, 1
jmp.z .next_space
; if we're here, we found a
; non-zero non-space character
mov q[argv1pos], rsi
; fallthrough
.do_extract:
; empty argv0
mov rcx, argbuf.size
mov rax, argv0
stosb.rep rax, zero
; how much do we copy?
sub rcx, rdx, argbuf
jmp.cxz .detect_builtin
dec rcx, 1
mov rdi, argbuf
mov rsi, argv0
.copy_loop:
mov b[rsi], b[rdi]
inc rdi, 1
inc rsi, 1
loop .copy_loop
.detect_builtin:
.builtin_cls = "cls"
call strcmp, argv0, .builtin_cls
jmp.axz .handle_CLS
.builtin_date = "date"
call strcmp, argv0, .builtin_date
jmp.axz .handle_DATE
.builtin_dir = "dir"
call strcmp, argv0, .builtin_dir
jmp.axz .handle_DIR
.builtin_dump = "dump"
call strcmp, argv0, .builtin_dump
jmp.axz .handle_DUMP
.builtin_echo = "echo"
call strcmp, argv0, .builtin_echo
jmp.axz .handle_ECHO
.builtin_exit = "exit"
call strcmp, argv0, .builtin_exit
jmp.axz .handle_EXIT
.builtin_help = "help"
call strcmp, argv0, .builtin_help
jmp.axz .handle_HELP
.builtin_halt = "halt"
call strcmp, argv0, .builtin_halt
jmp.axz .handle_HALT
.builtin_make = "make"
call strcmp, argv0, .builtin_make
jmp.axz .handle_MAKE
.builtin_print = "print"
call strcmp, argv0, .builtin_print
jmp.axz .handle_PRINT
.builtin_prompt = "prompt"
call strcmp, argv0, .builtin_prompt
jmp.axz .handle_PROMPT
.builtin_time = "time"
call strcmp, argv0, .builtin_time
jmp.axz .handle_TIME
.builtin_ver = "ver"
call strcmp, argv0, .builtin_ver
jmp.axz .handle_VER
jmp .command_not_found
;
; call builtins
;
.handle_CLS:
prn PRN_CLEAR
jmp .print_prompt
.handle_DATE:
call GetTimeUTC
push b[rax+3]
mov rcx, b[rax+4]
add rcx, rcx, 1
push rcx
push w[rax+6]
call printf, .datefmt
inc rsp, 40
jmp .print_prompt
.datefmt = "%d/%d/%d\n"
.handle_DIR:
call builtins.dir
jmp .print_prompt
.handle_DUMP:
dump
jmp .print_prompt
.handle_ECHO:
mov rdx, q[argv1pos]
jmp.dxz .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
jmp .print_prompt
.handle_HALT:
mov rax, Sys.EnterHaltMode
trap 0
jmp .print_prompt
.handle_MAKE:
mov rax, Sys.CreateFile
mov ax0, q[argv1pos]
b.z ax0, zero, .need_params
trap 0
b.l rax, zero, .couldnt_open
jmp .print_prompt
.handle_PRINT:
mov rax, Sys.OpenFile
mov ax0, q[argv1pos]
b.z ax0, zero, .need_params
trap 0
b.l rax, zero, .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 rcx, zero, .couldnt_read
jmp.cxz .empty_file
mov rdx, FILE_LOADP
prns.rep rdx
jmp .print_prompt
.handle_PROMPT:
mov ax0, prompt
mov ax1, q[argv1pos]
b.z ax1, zero, .need_params
call strcpy
jmp .print_prompt
.handle_TIME:
call GetTimeUTC
push b[rax]
push b[rax+1]
push b[rax+2]
call printf, .timefmt
inc rsp, 24
jmp .print_prompt
.timefmt = "%d:%d:%d\n"
.handle_VER:
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.exit
call print, .helpmsg.help
call print, .helpmsg.halt
call print, .helpmsg.make
call print, .helpmsg.print
call print, .helpmsg.prompt
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.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.time = " TIME Display current time of day\n"
.helpmsg.ver = " VER Display current COMMAND.COM version\n"
.command_not_found:
call print, argv0
call print, .cnf_errmsg
jmp .print_prompt
.cnf_errmsg = ": command not found\n"
.file_not_found:
push q[argv1pos]
push argv0
call printf, .fnf_errmsg
inc rsp, 16
jmp .print_prompt
.fnf_errmsg = "%s: %s: file not found\n"
.empty_file:
push q[argv1pos]
push argv0
call printf, .ef_errmsg
inc rsp, 16
jmp .print_prompt
.ef_errmsg = "%s: %s: file was empty\n"
.couldnt_open:
push q[argv1pos]
push argv0
call printf, .cno_errmsg
inc rsp, 16
jmp .print_prompt
.cno_errmsg = "%s: %s: an error occured while opening file\n"
.couldnt_read:
push q[argv1pos]
push 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"