zasm: add ERR_DUPSYM and ERR_OOM error conditions

This commit is contained in:
Virgil Dupras 2019-05-27 17:45:05 -04:00
parent b298e607bd
commit e414e600ea
7 changed files with 68 additions and 14 deletions

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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