mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-26 10:38:07 +11:00
Compare commits
No commits in common. "dcb96aefe9654504bebae79c0f9a1f1a5d6edbe8" and "15628da7de8703e9e6d9873e25289c50ab65bb14" have entirely different histories.
dcb96aefe9
...
15628da7de
@ -74,8 +74,6 @@ There are decimal, hexadecimal and binary literals. A "straight" number is
|
|||||||
parsed as a decimal. Hexadecimal literals must be prefixed with `0x` (`0xf4`).
|
parsed as a decimal. Hexadecimal literals must be prefixed with `0x` (`0xf4`).
|
||||||
Binary must be prefixed with `0b` (`0b01100110`).
|
Binary must be prefixed with `0b` (`0b01100110`).
|
||||||
|
|
||||||
A decimal literal cannot start with `0`, with the exception of the `0` literal.
|
|
||||||
|
|
||||||
Decimals and hexadecimal are "flexible". Whether they're written in a byte or
|
Decimals and hexadecimal are "flexible". Whether they're written in a byte or
|
||||||
a word, you don't need to prefix them with zeroes. Watch out for overflow,
|
a word, you don't need to prefix them with zeroes. Watch out for overflow,
|
||||||
however.
|
however.
|
||||||
|
@ -22,5 +22,6 @@ jp at28wMain
|
|||||||
.inc "core.asm"
|
.inc "core.asm"
|
||||||
.inc "lib/util.asm"
|
.inc "lib/util.asm"
|
||||||
.inc "lib/parse.asm"
|
.inc "lib/parse.asm"
|
||||||
|
.inc "lib/args.asm"
|
||||||
.inc "at28w/main.asm"
|
.inc "at28w/main.asm"
|
||||||
USER_RAMSTART:
|
USER_RAMSTART:
|
||||||
|
@ -11,15 +11,15 @@
|
|||||||
; *** Code ***
|
; *** Code ***
|
||||||
|
|
||||||
at28wMain:
|
at28wMain:
|
||||||
ld de, AT28W_MAXBYTES
|
ld de, .argspecs
|
||||||
ld a, (hl)
|
ld ix, AT28W_MAXBYTES
|
||||||
or a
|
call parseArgs
|
||||||
jr z, at28wInner ; no arg
|
|
||||||
call parseHexadecimal ; --> DE
|
|
||||||
jr z, at28wInner
|
jr z, at28wInner
|
||||||
; bad args
|
; bad args
|
||||||
ld a, SHELL_ERR_BAD_ARGS
|
ld a, SHELL_ERR_BAD_ARGS
|
||||||
ret
|
ret
|
||||||
|
.argspecs:
|
||||||
|
.db 0b111, 0b101, 0
|
||||||
|
|
||||||
at28wInner:
|
at28wInner:
|
||||||
; Reminder: words in parseArgs aren't little endian. High byte is first.
|
; Reminder: words in parseArgs aren't little endian. High byte is first.
|
||||||
|
111
apps/lib/args.asm
Normal file
111
apps/lib/args.asm
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
; *** Requirements ***
|
||||||
|
; lib/parse
|
||||||
|
;
|
||||||
|
; *** Consts ***
|
||||||
|
; maximum number of bytes to receive as args in all commands. Determines the
|
||||||
|
; size of the args variable.
|
||||||
|
.equ PARSE_ARG_MAXCOUNT 3
|
||||||
|
|
||||||
|
; *** Code ***
|
||||||
|
|
||||||
|
; Parse arguments at (HL) with specifiers at (DE) into (IX).
|
||||||
|
;
|
||||||
|
; Args specifiers are a series of flag for each arg:
|
||||||
|
; Bit 0 - arg present: if unset, we stop parsing there
|
||||||
|
; Bit 1 - is word: this arg is a word rather than a byte. Because our
|
||||||
|
; destination are bytes anyway, this doesn't change much except
|
||||||
|
; for whether we expect a space between the hex pairs. If set,
|
||||||
|
; you still need to have a specifier for the second part of
|
||||||
|
; the multibyte.
|
||||||
|
; Bit 2 - optional: If set and not present during parsing, we don't error out
|
||||||
|
; and write zero
|
||||||
|
;
|
||||||
|
; Bit 3 - String argument: If set, this argument is a string. A pointer to the
|
||||||
|
; read string, null terminated (max 0x20 chars) will
|
||||||
|
; be placed in the next two bytes. This has to be the
|
||||||
|
; last argument of the list and it stops parsing.
|
||||||
|
; Sets A to nonzero if there was an error during parsing, zero otherwise.
|
||||||
|
parseArgs:
|
||||||
|
push bc
|
||||||
|
push de
|
||||||
|
push hl
|
||||||
|
push ix
|
||||||
|
|
||||||
|
; init the arg value to a default 0
|
||||||
|
xor a
|
||||||
|
ld (ix), a
|
||||||
|
ld (ix+1), a
|
||||||
|
ld (ix+2), a
|
||||||
|
ld b, PARSE_ARG_MAXCOUNT
|
||||||
|
.loop:
|
||||||
|
ld a, (hl)
|
||||||
|
; is this the end of the line?
|
||||||
|
or a ; cp 0
|
||||||
|
jr z, .endofargs
|
||||||
|
|
||||||
|
; Get the specs
|
||||||
|
ld a, (de)
|
||||||
|
bit 0, a ; do we have an arg?
|
||||||
|
jr z, .error ; not set? then we have too many args
|
||||||
|
|
||||||
|
ld c, a ; save the specs for multibyte check later
|
||||||
|
bit 3, a ; is our arg a string?
|
||||||
|
jr z, .notAString
|
||||||
|
; our arg is a string. Let's place HL in our next two bytes and call
|
||||||
|
; it a day. Little endian, remember
|
||||||
|
ld (ix), l
|
||||||
|
ld (ix+1), h
|
||||||
|
jr .success ; directly to success: skip endofargs checks
|
||||||
|
|
||||||
|
.notAString:
|
||||||
|
call parseHexPair
|
||||||
|
jr c, .error
|
||||||
|
|
||||||
|
; we have a good arg and we need to write A in (IX).
|
||||||
|
ld (ix), a
|
||||||
|
|
||||||
|
; Good! increase counters
|
||||||
|
inc de
|
||||||
|
inc ix
|
||||||
|
inc hl ; get to following char (generally a space)
|
||||||
|
|
||||||
|
; Our arg is parsed, our pointers are increased. Normally, HL should
|
||||||
|
; point to a space *unless* our argspec indicates a multibyte arg.
|
||||||
|
bit 1, c
|
||||||
|
jr nz, .nospacecheck ; bit set? no space check
|
||||||
|
; do we have a proper space char (or null char)?
|
||||||
|
ld a, (hl)
|
||||||
|
or a
|
||||||
|
jr z, .endofargs
|
||||||
|
cp ' '
|
||||||
|
jr nz, .error
|
||||||
|
inc hl
|
||||||
|
.nospacecheck:
|
||||||
|
djnz .loop
|
||||||
|
; If we get here, it means that our next char *has* to be a null char
|
||||||
|
ld a, (hl)
|
||||||
|
or a ; cp 0
|
||||||
|
jr z, .success ; zero? great!
|
||||||
|
jr .error
|
||||||
|
|
||||||
|
.endofargs:
|
||||||
|
; We encountered our null char. Let's verify that we either have no
|
||||||
|
; more args or that they are optional
|
||||||
|
ld a, (de)
|
||||||
|
or a
|
||||||
|
jr z, .success ; no arg? success
|
||||||
|
bit 2, a
|
||||||
|
jr z, .error ; if unset, arg is not optional. error
|
||||||
|
; success
|
||||||
|
.success:
|
||||||
|
xor a
|
||||||
|
jr .end
|
||||||
|
.error:
|
||||||
|
inc a
|
||||||
|
.end:
|
||||||
|
pop ix
|
||||||
|
pop hl
|
||||||
|
pop de
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
@ -22,6 +22,42 @@ parseHex:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Parses 2 characters of the string pointed to by HL and returns the numerical
|
||||||
|
; value in A. If the second character is a "special" character (<0x21) we don't
|
||||||
|
; error out: the result will be the one from the first char only.
|
||||||
|
; HL is set to point to the last char of the pair.
|
||||||
|
;
|
||||||
|
; On success, the carry flag is reset. On error, it is set.
|
||||||
|
parseHexPair:
|
||||||
|
push bc
|
||||||
|
|
||||||
|
ld a, (hl)
|
||||||
|
call parseHex
|
||||||
|
jr c, .end ; error? goto end, keeping the C flag on
|
||||||
|
rla \ rla \ rla \ rla ; let's push this in MSB
|
||||||
|
ld b, a
|
||||||
|
inc hl
|
||||||
|
ld a, (hl)
|
||||||
|
cp 0x21
|
||||||
|
jr c, .single ; special char? single digit
|
||||||
|
call parseHex
|
||||||
|
jr c, .end ; error?
|
||||||
|
or b ; join left-shifted + new. we're done!
|
||||||
|
; C flag was set on parseHex and is necessarily clear at this point
|
||||||
|
jr .end
|
||||||
|
|
||||||
|
.single:
|
||||||
|
; If we have a single digit, our result is already stored in B, but
|
||||||
|
; we have to right-shift it back.
|
||||||
|
ld a, b
|
||||||
|
and 0xf0
|
||||||
|
rra \ rra \ rra \ rra
|
||||||
|
dec hl
|
||||||
|
|
||||||
|
.end:
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
; Parse the decimal char at A and extract it's 0-9 numerical value. Put the
|
; Parse the decimal char at A and extract it's 0-9 numerical value. Put the
|
||||||
; result in A.
|
; result in A.
|
||||||
;
|
;
|
||||||
@ -104,45 +140,71 @@ parseDecimal:
|
|||||||
pop hl ; <-- lvl 1, orig
|
pop hl ; <-- lvl 1, orig
|
||||||
jp unsetZ
|
jp unsetZ
|
||||||
|
|
||||||
; Parse string at (HL) as a hexadecimal value without the "0x" prefix and
|
; Parse string at (HL) as a hexadecimal value and return value in DE under the
|
||||||
; return value in DE.
|
; same conditions as parseLiteral.
|
||||||
; HL is advanced to the character following the last successfully read char.
|
|
||||||
; Sets Z on success.
|
|
||||||
parseHexadecimal:
|
parseHexadecimal:
|
||||||
ld a, (hl)
|
call hasHexPrefix
|
||||||
call parseHex
|
ret nz
|
||||||
jp c, unsetZ ; we need at least one char
|
push hl
|
||||||
push bc
|
ld d, 0
|
||||||
ld de, 0
|
inc hl ; get rid of "0x"
|
||||||
ld b, 0
|
|
||||||
.loop:
|
|
||||||
; we push to B to verify overflow
|
|
||||||
rl e \ rl d \ rl b
|
|
||||||
rl e \ rl d \ rl b
|
|
||||||
rl e \ rl d \ rl b
|
|
||||||
rl e \ rl d \ rl b
|
|
||||||
or e
|
|
||||||
ld e, a
|
|
||||||
; did we overflow?
|
|
||||||
ld a, b
|
|
||||||
or a
|
|
||||||
jr nz, .end ; overflow, NZ already set
|
|
||||||
; next char
|
|
||||||
inc hl
|
inc hl
|
||||||
|
call strlen
|
||||||
|
cp 3
|
||||||
|
jr c, .single
|
||||||
|
cp 4
|
||||||
|
jr c, .doubleShort ; 0x123
|
||||||
|
cp 5
|
||||||
|
jr c, .double ; 0x1234
|
||||||
|
; too long, error
|
||||||
|
jr .error
|
||||||
|
.double:
|
||||||
|
call parseHexPair
|
||||||
|
jr c, .error
|
||||||
|
inc hl ; now HL is on first char of next pair
|
||||||
|
ld d, a
|
||||||
|
jr .single
|
||||||
|
.doubleShort:
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
call parseHex
|
call parseHex
|
||||||
jr nc, .loop
|
jr c, .error
|
||||||
cp a ; ensure Z
|
inc hl ; now HL is on first char of next pair
|
||||||
|
ld d, a
|
||||||
|
.single:
|
||||||
|
call parseHexPair
|
||||||
|
jr c, .error
|
||||||
|
ld e, a
|
||||||
|
cp a ; ensure Z
|
||||||
|
jr .end
|
||||||
|
.error:
|
||||||
|
call unsetZ
|
||||||
.end:
|
.end:
|
||||||
pop bc
|
pop hl
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Parse string at (HL) as a binary value (010101) without the "0b" prefix and
|
; Sets Z if (HL) has a '0x' prefix.
|
||||||
; return value in E. D is always zero.
|
hasHexPrefix:
|
||||||
|
ld a, (hl)
|
||||||
|
cp '0'
|
||||||
|
ret nz
|
||||||
|
push hl
|
||||||
|
inc hl
|
||||||
|
ld a, (hl)
|
||||||
|
cp 'x'
|
||||||
|
pop hl
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Parse string at (HL) as a binary value (0b010101) and return value in E.
|
||||||
|
; D is always zero.
|
||||||
; Sets Z on success.
|
; Sets Z on success.
|
||||||
parseBinaryLiteral:
|
parseBinaryLiteral:
|
||||||
|
call hasBinPrefix
|
||||||
|
ret nz
|
||||||
push bc
|
push bc
|
||||||
push hl
|
push hl
|
||||||
|
ld d, 0
|
||||||
|
inc hl ; get rid of "0b"
|
||||||
|
inc hl
|
||||||
call strlen
|
call strlen
|
||||||
or a
|
or a
|
||||||
jr z, .error ; empty, error
|
jr z, .error ; empty, error
|
||||||
@ -175,20 +237,17 @@ parseBinaryLiteral:
|
|||||||
pop bc
|
pop bc
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Parses the string at (HL) and returns the 16-bit value in DE. The string
|
; Sets Z if (HL) has a '0b' prefix.
|
||||||
; can be a decimal literal (1234), a hexadecimal literal (0x1234) or a char
|
hasBinPrefix:
|
||||||
; literal ('X').
|
|
||||||
;
|
|
||||||
; As soon as the number doesn't fit 16-bit any more, parsing stops and the
|
|
||||||
; number is invalid. If the number is valid, Z is set, otherwise, unset.
|
|
||||||
parseLiteral:
|
|
||||||
ld de, 0 ; pre-fill
|
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
cp 0x27 ; apostrophe
|
|
||||||
jr z, .char
|
|
||||||
cp '0'
|
cp '0'
|
||||||
jr z, .hexOrBin
|
ret nz
|
||||||
jp parseDecimal
|
push hl
|
||||||
|
inc hl
|
||||||
|
ld a, (hl)
|
||||||
|
cp 'b'
|
||||||
|
pop hl
|
||||||
|
ret
|
||||||
|
|
||||||
; Parse string at (HL) and, if it is a char literal, sets Z and return
|
; Parse string at (HL) and, if it is a char literal, sets Z and return
|
||||||
; corresponding value in E. D is always zero.
|
; corresponding value in E. D is always zero.
|
||||||
@ -196,45 +255,43 @@ parseLiteral:
|
|||||||
; A valid char literal starts with ', ends with ' and has one character in the
|
; A valid char literal starts with ', ends with ' and has one character in the
|
||||||
; middle. No escape sequence are accepted, but ''' will return the apostrophe
|
; middle. No escape sequence are accepted, but ''' will return the apostrophe
|
||||||
; character.
|
; character.
|
||||||
.char:
|
parseCharLiteral:
|
||||||
|
ld a, 0x27 ; apostrophe (') char
|
||||||
|
cp (hl)
|
||||||
|
ret nz
|
||||||
|
|
||||||
push hl
|
push hl
|
||||||
inc hl
|
inc hl
|
||||||
inc hl
|
inc hl
|
||||||
cp (hl)
|
cp (hl)
|
||||||
jr nz, .charEnd ; not ending with an apostrophe
|
jr nz, .end ; not ending with an apostrophe
|
||||||
inc hl
|
inc hl
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
or a ; cp 0
|
or a ; cp 0
|
||||||
jr nz, .charEnd ; string has to end there
|
jr nz, .end ; string has to end there
|
||||||
; Valid char, good
|
; Valid char, good
|
||||||
|
ld d, a ; A is zero, take advantage of that
|
||||||
dec hl
|
dec hl
|
||||||
dec hl
|
dec hl
|
||||||
ld e, (hl)
|
ld a, (hl)
|
||||||
|
ld e, a
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
.charEnd:
|
.end:
|
||||||
pop hl
|
pop hl
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.hexOrBin:
|
; Parses the string at (HL) and returns the 16-bit value in DE. The string
|
||||||
inc hl
|
; can be a decimal literal (1234), a hexadecimal literal (0x1234) or a char
|
||||||
ld a, (hl)
|
; literal ('X').
|
||||||
inc hl ; already place it for hex or bin
|
;
|
||||||
cp 'x'
|
; As soon as the number doesn't fit 16-bit any more, parsing stops and the
|
||||||
jr z, .hex
|
; number is invalid. If the number is valid, Z is set, otherwise, unset.
|
||||||
cp 'b'
|
parseLiteral:
|
||||||
jr z, .bin
|
call parseCharLiteral
|
||||||
; special case: single '0'. set Z if we hit have null terminating.
|
ret z
|
||||||
or a
|
|
||||||
.hexOrBinEnd:
|
|
||||||
dec hl \ dec hl ; replace HL
|
|
||||||
ret ; Z already set
|
|
||||||
|
|
||||||
.hex:
|
|
||||||
push hl
|
|
||||||
call parseHexadecimal
|
call parseHexadecimal
|
||||||
pop hl
|
ret z
|
||||||
jr .hexOrBinEnd
|
|
||||||
|
|
||||||
.bin:
|
|
||||||
call parseBinaryLiteral
|
call parseBinaryLiteral
|
||||||
jr .hexOrBinEnd
|
ret z
|
||||||
|
jp parseDecimal
|
||||||
|
|
||||||
|
@ -5,31 +5,6 @@ isWS:
|
|||||||
cp 0x09
|
cp 0x09
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Advance HL to next WS.
|
|
||||||
; Set Z if WS found, unset if end-of-string.
|
|
||||||
toWS:
|
|
||||||
ld a, (hl)
|
|
||||||
call isWS
|
|
||||||
ret z
|
|
||||||
or a
|
|
||||||
jp z, unsetZ
|
|
||||||
inc hl
|
|
||||||
jr toWS
|
|
||||||
|
|
||||||
; Consume following whitespaces in HL until a non-WS is hit.
|
|
||||||
; Set Z if non-WS found, unset if end-of-string.
|
|
||||||
rdWS:
|
|
||||||
ld a, (hl)
|
|
||||||
call isWS
|
|
||||||
jr nz, .ok
|
|
||||||
or a
|
|
||||||
jp z, unsetZ
|
|
||||||
inc hl
|
|
||||||
jr rdWS
|
|
||||||
.ok:
|
|
||||||
cp a ; ensure Z
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Copy string from (HL) in (DE), that is, copy bytes until a null char is
|
; Copy string from (HL) in (DE), that is, copy bytes until a null char is
|
||||||
; encountered. The null char is also copied.
|
; encountered. The null char is also copied.
|
||||||
; HL and DE point to the char right after the null char.
|
; HL and DE point to the char right after the null char.
|
||||||
|
@ -68,6 +68,7 @@ jp zasmMain
|
|||||||
.inc "lib/util.asm"
|
.inc "lib/util.asm"
|
||||||
.inc "lib/ari.asm"
|
.inc "lib/ari.asm"
|
||||||
.inc "lib/parse.asm"
|
.inc "lib/parse.asm"
|
||||||
|
.inc "lib/args.asm"
|
||||||
.inc "zasm/util.asm"
|
.inc "zasm/util.asm"
|
||||||
.equ IO_RAMSTART USER_RAMSTART
|
.equ IO_RAMSTART USER_RAMSTART
|
||||||
.inc "zasm/io.asm"
|
.inc "zasm/io.asm"
|
||||||
|
@ -25,6 +25,7 @@ jp zasmMain
|
|||||||
.inc "lib/util.asm"
|
.inc "lib/util.asm"
|
||||||
.inc "lib/ari.asm"
|
.inc "lib/ari.asm"
|
||||||
.inc "lib/parse.asm"
|
.inc "lib/parse.asm"
|
||||||
|
.inc "lib/args.asm"
|
||||||
.inc "zasm/util.asm"
|
.inc "zasm/util.asm"
|
||||||
.equ IO_RAMSTART USER_RAMSTART
|
.equ IO_RAMSTART USER_RAMSTART
|
||||||
.inc "zasm/io.asm"
|
.inc "zasm/io.asm"
|
||||||
|
@ -23,34 +23,34 @@
|
|||||||
; HL is set to the last lineno to be read.
|
; HL is set to the last lineno to be read.
|
||||||
; Sets Z on success, unset on error. On error, A contains an error code (ERR_*)
|
; Sets Z on success, unset on error. On error, A contains an error code (ERR_*)
|
||||||
zasmMain:
|
zasmMain:
|
||||||
; Parse args in (HL)
|
; Parse args. HL points to string already
|
||||||
; blkdev in
|
; We don't allocate memory just to hold this. Because this happens
|
||||||
call parseHexadecimal ; --> DE
|
; before initialization, we don't really care where those args are
|
||||||
jr nz, .badargs
|
; parsed. That's why we borrow zasm's RAMSTART for a little while.
|
||||||
ld a, e
|
ld de, .argspecs
|
||||||
|
ld ix, ZASM_RAMSTART
|
||||||
|
call parseArgs
|
||||||
|
jr z, .goodargs
|
||||||
|
; bad args
|
||||||
|
ld hl, 0
|
||||||
|
ld de, 0
|
||||||
|
ld a, SHELL_ERR_BAD_ARGS
|
||||||
|
ret
|
||||||
|
|
||||||
|
.goodargs:
|
||||||
|
; HL now points to parsed args
|
||||||
|
; Init I/O
|
||||||
|
ld a, (ZASM_RAMSTART) ; blkdev in ID
|
||||||
ld de, IO_IN_BLK
|
ld de, IO_IN_BLK
|
||||||
call blkSel
|
call blkSel
|
||||||
|
ld a, (ZASM_RAMSTART+1) ; blkdev out ID
|
||||||
; blkdev in
|
|
||||||
call rdWS
|
|
||||||
jr nz, .badargs
|
|
||||||
call parseHexadecimal ; --> DE
|
|
||||||
jr nz, .badargs
|
|
||||||
ld a, e
|
|
||||||
ld de, IO_OUT_BLK
|
ld de, IO_OUT_BLK
|
||||||
call blkSel
|
call blkSel
|
||||||
|
|
||||||
; .org high byte
|
; Init .org
|
||||||
ld e, 0 ; in case we .skipOrgSet
|
; This is the 3rd argument, optional, will be zero if not given.
|
||||||
call rdWS
|
|
||||||
jr nz, .skipOrgSet ; no org argument
|
|
||||||
call parseHexadecimal ; --> DE
|
|
||||||
jr nz, .badargs
|
|
||||||
|
|
||||||
.skipOrgSet:
|
|
||||||
; Init .org with value of E
|
|
||||||
; Save in "@" too
|
; Save in "@" too
|
||||||
ld a, e
|
ld a, (ZASM_RAMSTART+2)
|
||||||
ld (ZASM_ORG+1), a ; high byte of .org
|
ld (ZASM_ORG+1), a ; high byte of .org
|
||||||
ld (DIREC_LASTVAL+1), a
|
ld (DIREC_LASTVAL+1), a
|
||||||
xor a
|
xor a
|
||||||
@ -82,11 +82,8 @@ zasmMain:
|
|||||||
.end:
|
.end:
|
||||||
jp ioLineNo ; --> HL, --> DE, returns
|
jp ioLineNo ; --> HL, --> DE, returns
|
||||||
|
|
||||||
.badargs:
|
.argspecs:
|
||||||
; bad args
|
.db 0b001, 0b001, 0b101
|
||||||
ld a, SHELL_ERR_BAD_ARGS
|
|
||||||
ret
|
|
||||||
|
|
||||||
.sFirstPass:
|
.sFirstPass:
|
||||||
.db "First pass", 0
|
.db "First pass", 0
|
||||||
.sSecondPass:
|
.sSecondPass:
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
jp upcase
|
jp upcase
|
||||||
jp findchar
|
jp findchar
|
||||||
jp parseHex
|
jp parseHex
|
||||||
|
jp parseHexPair
|
||||||
jp blkSel
|
jp blkSel
|
||||||
jp blkSet
|
jp blkSet
|
||||||
jp fsFindFN
|
jp fsFindFN
|
||||||
@ -144,9 +145,9 @@ basFindCmdExtra:
|
|||||||
jp basPgmHook
|
jp basPgmHook
|
||||||
.mycmds:
|
.mycmds:
|
||||||
.db "ed", 0
|
.db "ed", 0
|
||||||
.dw 0x1f00
|
.dw 0x1e00
|
||||||
.db "zasm", 0
|
.db "zasm", 0
|
||||||
.dw 0x2400
|
.dw 0x2300
|
||||||
.db 0xff
|
.db 0xff
|
||||||
|
|
||||||
f0GetB:
|
f0GetB:
|
||||||
@ -165,13 +166,13 @@ f1PutB:
|
|||||||
ld ix, FS_HANDLES+FS_HANDLE_SIZE
|
ld ix, FS_HANDLES+FS_HANDLE_SIZE
|
||||||
jp fsPutB
|
jp fsPutB
|
||||||
|
|
||||||
; last time I checked, PC at this point was 0x1e92. Let's give us a nice margin
|
; last time I checked, PC at this point was 0x1df8. Let's give us a nice margin
|
||||||
; for the start of ed.
|
; for the start of ed.
|
||||||
.fill 0x1f00-$
|
.fill 0x1e00-$
|
||||||
.bin "ed.bin"
|
.bin "ed.bin"
|
||||||
|
|
||||||
; Last check: 0x23b0
|
; Last check: 0x22dd
|
||||||
.fill 0x2400-$
|
.fill 0x2300-$
|
||||||
.bin "zasm.bin"
|
.bin "zasm.bin"
|
||||||
|
|
||||||
.fill 0x7ff0-$
|
.fill 0x7ff0-$
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
.equ upcase @+3
|
.equ upcase @+3
|
||||||
.equ findchar @+3
|
.equ findchar @+3
|
||||||
.equ parseHex @+3
|
.equ parseHex @+3
|
||||||
|
.equ parseHexPair @+3
|
||||||
.equ blkSel @+3
|
.equ blkSel @+3
|
||||||
.equ blkSet @+3
|
.equ blkSet @+3
|
||||||
.equ fsFindFN @+3
|
.equ fsFindFN @+3
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
jp test
|
|
||||||
|
|
||||||
.inc "core.asm"
|
|
||||||
.inc "lib/util.asm"
|
|
||||||
.inc "lib/parse.asm"
|
|
||||||
|
|
||||||
zasmGetPC:
|
|
||||||
ret
|
|
||||||
|
|
||||||
testNum: .db 1
|
|
||||||
|
|
||||||
test:
|
|
||||||
ld sp, 0xffff
|
|
||||||
|
|
||||||
call testParseHex
|
|
||||||
call testParseHexadecimal
|
|
||||||
|
|
||||||
; success
|
|
||||||
xor a
|
|
||||||
halt
|
|
||||||
|
|
||||||
testParseHex:
|
|
||||||
ld a, '8'
|
|
||||||
call parseHex
|
|
||||||
jp c, fail
|
|
||||||
cp 8
|
|
||||||
jp nz, fail
|
|
||||||
call nexttest
|
|
||||||
|
|
||||||
ld a, 'e'
|
|
||||||
call parseHex
|
|
||||||
jp c, fail
|
|
||||||
cp 0xe
|
|
||||||
jp nz, fail
|
|
||||||
call nexttest
|
|
||||||
|
|
||||||
ld a, 'x'
|
|
||||||
call parseHex
|
|
||||||
jp nc, fail
|
|
||||||
call nexttest
|
|
||||||
ret
|
|
||||||
|
|
||||||
testParseHexadecimal:
|
|
||||||
ld hl, .s99
|
|
||||||
call parseHexadecimal
|
|
||||||
jp nz, fail
|
|
||||||
ld a, e
|
|
||||||
cp 0x99
|
|
||||||
jp nz, fail
|
|
||||||
call nexttest
|
|
||||||
|
|
||||||
ld hl, .saB
|
|
||||||
call parseHexadecimal
|
|
||||||
jp nz, fail
|
|
||||||
ld a, e
|
|
||||||
cp 0xab
|
|
||||||
jp nz, fail
|
|
||||||
call nexttest
|
|
||||||
|
|
||||||
; The string "Foo" will not cause a failure. We will parse up to "o"
|
|
||||||
; and then stop.
|
|
||||||
ld hl, .sFoo
|
|
||||||
call parseHexadecimal
|
|
||||||
jp nz, fail
|
|
||||||
ld a, e
|
|
||||||
cp 0xf
|
|
||||||
call nexttest
|
|
||||||
ret
|
|
||||||
|
|
||||||
.sFoo: .db "Foo", 0
|
|
||||||
.saB: .db "aB", 0
|
|
||||||
.s99: .db "99", 0
|
|
||||||
|
|
||||||
nexttest:
|
|
||||||
ld a, (testNum)
|
|
||||||
inc a
|
|
||||||
ld (testNum), a
|
|
||||||
ret
|
|
||||||
|
|
||||||
fail:
|
|
||||||
ld a, (testNum)
|
|
||||||
halt
|
|
||||||
|
|
||||||
; used as RAM
|
|
||||||
sandbox:
|
|
136
tools/tests/unit/test_parse.asm
Normal file
136
tools/tests/unit/test_parse.asm
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
jp test
|
||||||
|
|
||||||
|
.inc "core.asm"
|
||||||
|
.inc "lib/util.asm"
|
||||||
|
.inc "lib/parse.asm"
|
||||||
|
.inc "lib/args.asm"
|
||||||
|
|
||||||
|
zasmGetPC:
|
||||||
|
ret
|
||||||
|
|
||||||
|
testNum: .db 1
|
||||||
|
|
||||||
|
test:
|
||||||
|
ld hl, 0xffff
|
||||||
|
ld sp, hl
|
||||||
|
|
||||||
|
call testParseHex
|
||||||
|
call testParseHexPair
|
||||||
|
call testParseArgs
|
||||||
|
|
||||||
|
; success
|
||||||
|
xor a
|
||||||
|
halt
|
||||||
|
|
||||||
|
testParseHex:
|
||||||
|
ld a, '8'
|
||||||
|
call parseHex
|
||||||
|
jp c, fail
|
||||||
|
cp 8
|
||||||
|
jp nz, fail
|
||||||
|
call nexttest
|
||||||
|
|
||||||
|
ld a, 'e'
|
||||||
|
call parseHex
|
||||||
|
jp c, fail
|
||||||
|
cp 0xe
|
||||||
|
jp nz, fail
|
||||||
|
call nexttest
|
||||||
|
|
||||||
|
ld a, 'x'
|
||||||
|
call parseHex
|
||||||
|
jp nc, fail
|
||||||
|
call nexttest
|
||||||
|
ret
|
||||||
|
|
||||||
|
testParseHexPair:
|
||||||
|
ld hl, .s99
|
||||||
|
call parseHexPair
|
||||||
|
jp c, fail
|
||||||
|
cp 0x99
|
||||||
|
jp nz, fail
|
||||||
|
call nexttest
|
||||||
|
|
||||||
|
ld hl, .saB
|
||||||
|
call parseHexPair
|
||||||
|
jp c, fail
|
||||||
|
cp 0xab
|
||||||
|
jp nz, fail
|
||||||
|
call nexttest
|
||||||
|
|
||||||
|
ld hl, .sFoo
|
||||||
|
call parseHexPair
|
||||||
|
jp nc, fail
|
||||||
|
call nexttest
|
||||||
|
ret
|
||||||
|
|
||||||
|
.sFoo: .db "Foo", 0
|
||||||
|
.saB: .db "aB", 0
|
||||||
|
.s99: .db "99", 0
|
||||||
|
|
||||||
|
|
||||||
|
testParseArgs:
|
||||||
|
ld hl, .t1+6
|
||||||
|
ld de, .t1
|
||||||
|
ld iy, .t1+3
|
||||||
|
call .testargs
|
||||||
|
|
||||||
|
ld hl, .t2+6
|
||||||
|
ld de, .t2
|
||||||
|
ld iy, .t2+3
|
||||||
|
call .testargs
|
||||||
|
|
||||||
|
ld hl, .t3+6
|
||||||
|
ld de, .t3
|
||||||
|
ld iy, .t3+3
|
||||||
|
call .testargs
|
||||||
|
ret
|
||||||
|
|
||||||
|
; HL and DE must be set, and IY must point to expected results in IX
|
||||||
|
.testargs:
|
||||||
|
ld ix, sandbox
|
||||||
|
call parseArgs
|
||||||
|
jp nz, fail
|
||||||
|
ld a, (ix)
|
||||||
|
cp (iy)
|
||||||
|
jp nz, fail
|
||||||
|
ld a, (ix+1)
|
||||||
|
cp (iy+1)
|
||||||
|
jp nz, fail
|
||||||
|
ld a, (ix+2)
|
||||||
|
cp (iy+2)
|
||||||
|
jp nz, fail
|
||||||
|
jp nexttest
|
||||||
|
|
||||||
|
; Test data format: 3 bytes specs, 3 bytes expected (IX), then the arg string.
|
||||||
|
|
||||||
|
; Empty args with empty specs
|
||||||
|
.t1:
|
||||||
|
.db 0b0000, 0b0000, 0b0000
|
||||||
|
.db 0, 0, 0
|
||||||
|
.db 0
|
||||||
|
|
||||||
|
; One arg, one byte spec
|
||||||
|
.t2:
|
||||||
|
.db 0b0001, 0b0000, 0b0000
|
||||||
|
.db 0xe4, 0, 0
|
||||||
|
.db "e4", 0
|
||||||
|
|
||||||
|
; 3 args, 3 bytes spec
|
||||||
|
.t3:
|
||||||
|
.db 0b0001, 0b0001, 0b0001
|
||||||
|
.db 0xe4, 0xab, 0x99
|
||||||
|
.db "e4 ab 99", 0
|
||||||
|
|
||||||
|
nexttest:
|
||||||
|
ld a, (testNum)
|
||||||
|
inc a
|
||||||
|
ld (testNum), a
|
||||||
|
ret
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ld a, (testNum)
|
||||||
|
halt
|
||||||
|
|
||||||
|
; used as RAM
|
||||||
|
sandbox:
|
Loading…
Reference in New Issue
Block a user