zasm: add ERR_DUPSYM and ERR_OOM error conditions
This commit is contained in:
parent
b298e607bd
commit
e414e600ea
@ -13,3 +13,9 @@
|
||||
.equ ERR_OVFL 0x04
|
||||
|
||||
.equ ERR_FILENOTFOUND 0x05
|
||||
|
||||
; Duplicate symbol
|
||||
.equ ERR_DUPSYM 0x06
|
||||
|
||||
; Out of memory
|
||||
.equ ERR_OOM 0x07
|
||||
|
@ -104,6 +104,8 @@ handleDW:
|
||||
ret
|
||||
|
||||
handleEQU:
|
||||
call zasmIsLocalPass ; Are we in local pass? Then ignore all .equ.
|
||||
jr z, .skip ; they mess up duplicate symbol detection.
|
||||
push hl
|
||||
push de
|
||||
push bc
|
||||
@ -124,8 +126,7 @@ handleEQU:
|
||||
jr nz, .badarg
|
||||
ld hl, DIREC_SCRATCHPAD
|
||||
push ix \ pop de
|
||||
call symRegister ; TODO: handle duplicate symbol error, OOM, etc.
|
||||
cp a ; ensure Z
|
||||
call symRegister ; A and Z set
|
||||
jr .end
|
||||
.badfmt:
|
||||
ld a, ERR_BAD_FMT
|
||||
@ -139,6 +140,10 @@ handleEQU:
|
||||
pop de
|
||||
pop hl
|
||||
ret
|
||||
.skip:
|
||||
; consume args and return
|
||||
call readWord
|
||||
jp readWord
|
||||
|
||||
handleORG:
|
||||
call readWord
|
||||
|
@ -120,8 +120,7 @@ _parseInstr:
|
||||
|
||||
_parseDirec:
|
||||
ld a, c ; D_*
|
||||
call parseDirective
|
||||
ret
|
||||
jp parseDirective
|
||||
|
||||
_parseLabel:
|
||||
; The string in (scratchpad) is a label with its trailing ':' removed.
|
||||
|
@ -11,11 +11,6 @@
|
||||
; and continue second pass as usual.
|
||||
|
||||
; *** Constants ***
|
||||
; Duplicate symbol in registry
|
||||
.equ SYM_ERR_DUPLICATE 0x01
|
||||
; Symbol registry buffer is full
|
||||
.equ SYM_ERR_FULLBUF 0x02
|
||||
|
||||
; Maximum number of symbols we can have in the global registry
|
||||
.equ SYM_MAXCOUNT 0x200
|
||||
; Maximum number of symbols we can have in the local registry
|
||||
@ -153,7 +148,7 @@ symNamesEnd:
|
||||
; Register label in (HL) (minus the ending ":") into the symbol registry and
|
||||
; set its value in that registry to DE.
|
||||
; If successful, Z is set and A is the symbol index. Otherwise, Z is unset and
|
||||
; A is an error code (SYM_ERR_*).
|
||||
; A is an error code (ERR_*).
|
||||
symRegister:
|
||||
call symFind
|
||||
jr z, .alreadyThere
|
||||
@ -167,7 +162,7 @@ symRegister:
|
||||
ld c, a ; save that strlen for later
|
||||
|
||||
call symNamesEnd
|
||||
jr nz, .error
|
||||
jr nz, .outOfMemory
|
||||
|
||||
; Is our new name going to make us go out of bounds?
|
||||
push hl
|
||||
@ -178,7 +173,7 @@ symRegister:
|
||||
call cpHLDE
|
||||
pop de
|
||||
pop hl
|
||||
jr nc, .error ; HL >= DE
|
||||
jr nc, .outOfMemory ; HL >= DE
|
||||
|
||||
; Success. At this point, we have:
|
||||
; HL -> where we want to add the string
|
||||
@ -201,16 +196,37 @@ symRegister:
|
||||
; list. DE is already correctly placed, A is already zero
|
||||
ld (de), a
|
||||
|
||||
cp a ; ensure Z
|
||||
; Nothing to pop. We've already popped our stack in the lines above.
|
||||
ret
|
||||
|
||||
.error:
|
||||
.outOfMemory:
|
||||
ld a, ERR_OOM
|
||||
call unsetZ
|
||||
pop de
|
||||
pop hl
|
||||
ret
|
||||
|
||||
.alreadyThere:
|
||||
; We are in a tricky situation with regards to our handling of the
|
||||
; duplicate symbol error. Normally, it should be straightforward: We
|
||||
; only register labels during first pass and evaluate constants during
|
||||
; the second. Easy.
|
||||
; We can *almost* do that... but we have ".org". .org affects label
|
||||
; values and supports expressions, which means that we have to evaluate
|
||||
; constants during first pass. But because we can possibly have forward
|
||||
; references in ".equ", some constants are going to have a bad value.
|
||||
; Therefore, we really can't evaluate all constants during the first
|
||||
; pass.
|
||||
; With this situation, how do you manage detection of duplicate symbols?
|
||||
; By limiting the "duplicate error" condition to the first pass. During,
|
||||
; first pass, sure, we don't have our proper values, but we have all our
|
||||
; symbol names. So, if we end up in .alreadyThere during first pass,
|
||||
; then it's an error condition. If it's not first pass, then we need
|
||||
; to update our value.
|
||||
call zasmIsFirstPass
|
||||
jr z, .duplicateError
|
||||
; Second pass. Don't error out, just update value
|
||||
push hl
|
||||
ld hl, (SYM_CTX_PTR)
|
||||
ex de, hl
|
||||
@ -218,6 +234,9 @@ symRegister:
|
||||
pop hl
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
.duplicateError:
|
||||
ld a, ERR_DUPSYM
|
||||
jp unsetZ ; return
|
||||
|
||||
; Select global or local registry according to label name in (HL)
|
||||
symSelect:
|
||||
@ -246,7 +265,6 @@ symFind:
|
||||
inc ix
|
||||
inc ix
|
||||
jr .loop
|
||||
; exhausted djnz? no match
|
||||
.nomatch:
|
||||
call unsetZ
|
||||
jr .end
|
||||
|
@ -4,6 +4,7 @@ jp test
|
||||
#include "core.asm"
|
||||
#include "parse.asm"
|
||||
#include "zasm/util.asm"
|
||||
#include "zasm/const.asm"
|
||||
#include "zasm/parse.asm"
|
||||
.equ SYM_RAMSTART RAMSTART
|
||||
#include "zasm/symbol.asm"
|
||||
|
@ -3,9 +3,14 @@ jp test
|
||||
|
||||
#include "core.asm"
|
||||
#include "zasm/util.asm"
|
||||
#include "zasm/const.asm"
|
||||
.equ SYM_RAMSTART RAMSTART
|
||||
#include "zasm/symbol.asm"
|
||||
|
||||
; Pretend that we aren't in first pass
|
||||
zasmIsFirstPass:
|
||||
jp unsetZ
|
||||
|
||||
testNum: .db 1
|
||||
|
||||
sFOO: .db "FOO", 0
|
||||
|
@ -16,6 +16,24 @@ chkerr() {
|
||||
fi
|
||||
}
|
||||
|
||||
chkoom() {
|
||||
echo "Trying OOM error..."
|
||||
local s=""
|
||||
# 300 x 27-29 bytes > 8192 bytes. Large enough to smash the pool.
|
||||
for i in {1..300}; do
|
||||
s+=".equ abcdefghijklmnopqrstuvwxyz$i 42"
|
||||
s+=$'\n'
|
||||
done
|
||||
${ZASM} <<< "$s" > /dev/null
|
||||
local res=$?
|
||||
if [[ $res == 7 ]]; then
|
||||
echo "Good!"
|
||||
else
|
||||
echo "$res != 7"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
chkerr "foo" 1
|
||||
chkerr "ld a, foo" 2
|
||||
chkerr "ld a, hl" 2
|
||||
@ -37,3 +55,5 @@ chkerr "#inc foo" 3
|
||||
chkerr "ld a, 0x100" 4
|
||||
chkerr ".db 0x100" 4
|
||||
chkerr "#inc \"doesnotexist\"" 5
|
||||
chkerr ".equ foo 42 \\ .equ foo 42" 6
|
||||
chkoom
|
||||
|
Loading…
Reference in New Issue
Block a user