Skip to content

Commit

Permalink
Add echo and expr + tweak parse
Browse files Browse the repository at this point in the history
Adds new trivial initial versions of expr and echo, and prepares parse + strutils to be able to do more.
  • Loading branch information
sijnstra committed Jan 21, 2024
1 parent 757de8f commit 8ccc3e3
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 6 deletions.
2 changes: 1 addition & 1 deletion romdisk/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ BIN=init.bin
# Source files to assemble
SRCS=init.asm parse.asm ls.asm less.asm opt.asm mkdir.asm cd.asm rm.asm \
errors.asm uart.asm strutils.asm date.asm cp.asm misc.asm hexdump.asm \
sleep.asm
sleep.asm arith.asm expr.asm echo.asm
# Output directory to place binaries in
BUILDIR=build

Expand Down
25 changes: 25 additions & 0 deletions romdisk/arith.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; SPDX-FileCopyrightText: 2024 Shawn Sijnstra <shawn@sijnstra.com>
;
; SPDX-License-Identifier: Apache-2.0

SECTION TEXT

;------------------------------------------------------------------------
;
;
; 16-bit compare of HL and BC
; Equivalent to expected behaviour of "CP HL,BC"
; Parameters:
; HL - Base
; BC - Target
; Returns:
; Z and C flags set according to comparison
; Alters:
; F

PUBLIC cphlbc
cphlbc: push hl
and a
sbc hl,bc
pop hl
ret
60 changes: 60 additions & 0 deletions romdisk/echo.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
; SPDX-FileCopyrightText: 2024 Shawn Sijnstra <shawn@sijnstra.com>
;
; SPDX-License-Identifier: Apache-2.0


INCLUDE "zos_sys.asm"

SECTION TEXT

EXTERN error_print
EXTERN strlen

MACRO ERR_CHECK goto_label
or a
jp nz, goto_label
ENDM

; "echo" command main function
; Parameters:
; HL - ARGV
; BC - ARGC
; Returns:
; A - 0 on success
PUBLIC echo_main
echo_main:
; Check that argc is at 2 (command itself is part of argc)
ld a, c
cp 2
jp nz, _echo_usage
; Retrieve the number given as a parameter
inc hl
inc hl ; skip the first pointer
ld e,(hl) ;grab 2nd pointer
inc hl
ld d,(hl)
ex de,hl ;pointer in HL
call strlen ;returns answer in BC
ex de,hl ;DE has the string address
S_WRITE1(DEV_STDOUT) ;DE has address, BC has length
S_WRITE3(DEV_STDOUT, str_usage_end -1,1) ;newline
xor a ;success
ret


_echo_usage:
S_WRITE3(DEV_STDOUT, str_usage, str_usage_end - str_usage)
ld a, 1
ret

_echo_error:
; Give NULL to error_print to have a default error message
ld de, 0
call error_print
ld a, 2
ret

str_usage: DEFM "usage:\n"
DEFM " echo <string> sends a copy of <string> to STDOUT\n"
str_usage_end:

129 changes: 129 additions & 0 deletions romdisk/expr.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
; SPDX-FileCopyrightText: 2024 Shawn Sijnstra <shawn@sijnstra.com>
;
; SPDX-License-Identifier: Apache-2.0


INCLUDE "zos_sys.asm"
INCLUDE "zos_err.asm"

SECTION TEXT

EXTERN error_print
EXTERN parse_int
EXTERN strlen
EXTERN byte_to_ascii
EXTERN word_to_ascii_dec_u16

MACRO ERR_CHECK goto_label
or a
jp nz, goto_label
ENDM

; "expr" command main function
; Parameters:
; HL - ARGV
; BC - ARGC
; Returns:
; A - 0 on success
PUBLIC expr_main
expr_main:

; Retrieve the number given as a parameter
inc hl
inc hl ; skip the first pointer
ld e,(hl) ;grab 2nd pointer
inc hl
ld d,(hl)
ex de,hl ;pointer in HL
; Check that argc is at least 2 (command itself is part of argc)
; This may need to change in future as we allow to evaluate full expressions
ld a, c
sub 2
jp c, _expr_usage
jp nz, _expr_do_string ;can only be string related function now

_expr_do_math:
call parse_int ;strutils - accepts 16 bit dec or hex input at HL
or a ;0 is ok, 1 is overflow, 2 is bad digit
jr nz,_expr_usage
; Routine displaying the value of HL in decimal then hex
; Parameters:
; HL - number to display
; Returns:
; A - zero
; successful return to ZealOS

_expr_print_result:
push hl
ld de,_expr_buff
call word_to_ascii_dec_u16
ld hl,_expr_buff
ex de,hl
or a
sbc hl,de
ld b,h
ld c,l
S_WRITE2(DEV_STDOUT, _expr_buff)
S_WRITE3(DEV_STDOUT, str_gap,3)
pop hl
ld a,h
call byte_to_ascii
ld a,d
ld d,e
ld e,a
ld (_expr_buff),de
ld a,l
call byte_to_ascii
ld a,d
ld d,e
ld e,a
ld (_expr_buff+2),de
ld a,'\n'
ld (_expr_buff+4),a
S_WRITE3(DEV_STDOUT, _expr_buff,5)
xor a
ret

_expr_do_string:
; Check that argc is 3 (command itself is part of argc)
; format is "expr l string" which outputs the length of the string
dec a
jp nz, _expr_usage
ld a,(hl)
cp 'l'
jp nz,_expr_error ;it's not the 'length' command so invalid parameter.
ex de,hl ;hl back to pointer table
inc hl ; we didn't inc before
ld e,(hl) ;grab 3rd pointer
inc hl
ld d,(hl)
ex de,hl ;pointer in HL
call strlen ;returns answer in BC
ld h,b
ld l,c
jp _expr_print_result


_expr_usage:
S_WRITE3(DEV_STDOUT, str_usage, str_usage_end - str_usage)
ld a, 1
ret

_expr_error:
; Give NULL to error_print to have a default error message
ld de, 0
ld a, ERR_INVALID_PARAMETER
call error_print
ld a,2
ret

str_usage: DEFM "usage:\n"
DEFM " expr <X> evaluate the hex or decimal number <X>\n" ;this will be ((expression)) when ready
DEFM " expr l <string> evaluate the length of string\n"
DEFM " Results are shown in decimal and hex\n"
str_usage_end:
str_gap: DEFM " 0x"

SECTION DATA
_expr_buff: defs 5 ;largest number '65535'
50 changes: 46 additions & 4 deletions romdisk/parse.asm
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,55 @@ _prepare_argv_argc_loop:
or a
jr z, _prepare_argv_argc_end
; Check if the character is a quote
ld a, '\''
ld a, '\'' ;accept single quote as a string
cp (hl)
jp z, _prepare_argv_argc_quote_start
ld a, '\"' ;accept double quote as a string
cp (hl)
jp z, _prepare_argv_argc_quote_start
ld a, '('
cp (hl)
jp nz, _prepare_argv_argc_no_quote
_prepare_argv_argc_parenth:
inc hl
push hl ;this will end up in DE return value
dec hl ;so the loop works
ld e,1 ;this is the count of parentheses depth
_prepare_argv_argc_parenth_lp:
inc hl
dec bc
ld a,b
or c
jr z,_prepare_argv_argc_parenth_bad
ld a,(hl)
or a ;should not be terminator
jr z,_prepare_argv_argc_parenth_bad
cp '('
jr nz,_prepare_argv_argc_parenth_not_open
inc e ;increase count of open parenth
jr _prepare_argv_argc_parenth_lp
_prepare_argv_argc_parenth_not_open:
cp ')' ;decrease count of open parenth
jr nz,_prepare_argv_argc_parenth_lp
dec e
jr nz,_prepare_argv_argc_parenth_lp
xor a
ld (hl),a
inc a ;will become 0 for success below
_prepare_argv_argc_parenth_bad: ;assumes a=0 for bad.
dec a
inc hl
dec bc
ex de,hl
pop hl
jr _prepare_argv_argc_quote_process_end

_prepare_argv_argc_quote_start:
inc hl
dec bc
; Look for the closing quote
call memsep
_prepare_argv_argc_quote_process_end:
or a
jp nz, _prepare_argv_argc_error
; Next parameter, in DE, should begin with either ' ' or 0
Expand All @@ -328,8 +370,6 @@ _prepare_argv_argc_quote:
cpl ; Complement of A to have: 0 is not finished, 0xff is finished
inc de
push af
; Decrementing HL will make the parameter start with '
dec hl
jp _prepare_argv_argc_save_arg
_prepare_argv_argc_no_quote:
ld a, ' '
Expand Down Expand Up @@ -366,7 +406,7 @@ _prepare_argv_argc_save_arg:
pop af
; If A is not null, we reached the end of the command line
or a
jr z, _prepare_argv_argc_loop
jp z, _prepare_argv_argc_loop
_prepare_argv_argc_end:
ld a, (command_argc)
ld c, a
Expand Down Expand Up @@ -440,7 +480,9 @@ system_commands_begin:
NEW_COMMAND("clear", clear_main)
NEW_COMMAND("cp", cp_main)
NEW_COMMAND("date", date_main)
NEW_COMMAND("echo", echo_main)
NEW_COMMAND("exec", exec_main)
NEW_COMMAND("expr", expr_main)
NEW_COMMAND("help", help_main)
NEW_COMMAND("hexdump", hexdump_main)
NEW_COMMAND("less", less_main)
Expand Down
64 changes: 63 additions & 1 deletion romdisk/strutils.asm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

SECTION TEXT

EXTERN cphlbc

; Look for the delimiter A in the string pointed by HL
; Once it finds it, the token is replace by \0.
; Parameters:
Expand Down Expand Up @@ -360,6 +362,66 @@ _parse_upper_hex_digit:
sub 'A' - 10 ; CY will be reset
ret

; Convert a 16-bit value to ASCII (u16 decimal)
; Parameters:
; HL - 16 bit value to display
; DE - String destination. It must have at least 5 free bytes to write the ASCII result.
;
; Returns:
; DE - location of last character +1
; Alters:
; A, DE
PUBLIC word_to_ascii_dec_u16
word_to_ascii_dec_u16:
push bc
push hl
ld bc,10000
call cphlbc
jr nc,_word_to_ascii_u16_dig5
ld bc,1000
call cphlbc
jr nc,_word_to_ascii_u16_dig4
ld bc,100
call cphlbc
jr nc,_word_to_ascii_u16_dig3
ld a,l
cp 10
jr nc,_word_to_ascii_u16_dig2 ;>=10
jr _word_to_ascii_u16_dig1
;
_word_to_ascii_u16_dig5:
ld bc,-10000
call _do_digit
_word_to_ascii_u16_dig4:
ld bc,-1000
call _do_digit
_word_to_ascii_u16_dig3:
ld bc,-100
call _do_digit
_word_to_ascii_u16_dig2:
ld bc,-10
call _do_digit
ld a,l
_word_to_ascii_u16_dig1:
add a,'0'
ld (de),a
inc de
pop hl
pop bc
ret
;
_do_digit:
ld a,'0'-1
_do_digit_lp:
inc a
add hl,bc
jr c,_do_digit_lp
sbc hl,bc
ld (de),a
inc de
ret



; Convert a 32-bit value to ASCII (hex)
; Parameters:
Expand All @@ -369,7 +431,7 @@ _parse_upper_hex_digit:
; HL - HL + 4
; DE - DE + 8
; Alters:
; A, DE
; A, DE, HL
PUBLIC dword_to_ascii
dword_to_ascii:
push bc
Expand Down

0 comments on commit 8ccc3e3

Please sign in to comment.