4cade/src/parse.common.a

146 lines
4.1 KiB
Plaintext

;license:MIT
;(c) 2018 by 4am
;
; generic key/value text parser
;
; Public functions:
; - ParseKeyValueList
;
; Public variables:
; - gAttractModeStore
; - gFXStore
; - gDFXStore
; - gSlideshowStore
;
gAttractModeStore
!word $6000
gFXStore
!word $6000
gDFXStore
!word $6000
gSlideshowStore
!word $0800
;------------------------------------------------------------------------------
; ParseKeyValueList
; parse buffer with KEY=VALUE lines of a text file into an okvs
; keys and values limited to 127 characters, which should be enough for anyone
; if '=' is missing, key is kept and value is a 0-length string
; blank lines are ignored
; '#' character at beginning of line is a comment, entire line is ignored
; '[' character at beginning of line exits the parser
;
; in: stack contains 4 bytes of parameters:
; +1 [word] handle to storage space for okvs
; +3 [word] handle to buffer containing contents of text file
; +5 [byte] max length for okvs records (or 0)
; out: all registers and flags clobbered
; $1F00..$1FFF clobbered
; $00/$01 clobbered
; $02/$03 clobbered
; $04/$05 has the address of the next available byte after the okvs
; $FE/$FF clobbered
;------------------------------------------------------------------------------
ParseKeyValueList
+PARAMS_ON_STACK 5
+LDPARAM 1
+STAY @store1
+STAY @store2
+LDPARAM 3
+STAY $FE
ldy #5
lda (PARAM),y
sta @maxLength
ldy #0
lda ($FE),y
pha
iny
lda ($FE),y
tay
pla
sec
sbc #$01
sta $FE
bcs +
dey
+ sty $FF
jsr okvs_init ; reset key/value store
@store1 !word $FDFD ; SMC
ldy #$00 ; index into ($FE) pointing to current character
@newkey ldx #$00 ; X = index into current key
stx gValLen ; initialize value length (in case this line has no value)
jsr IncAndGetChar
cmp #$0D ; CR in first position (blank line) -> no key
beq @newkey
cmp #$23 ; '#' starts a comment -> no key, skip to CR
beq @skipLine
cmp #$5B ; '[' ends the parsing
beq .parseKeyValueDone
bne @appendToKey
@gatherKey
jsr IncAndGetChar
cmp #$0D ; CR -> finalize key, no value
beq @finalizeKey
cmp #$3D ; '=' -> finalize key, start gathering value
beq @finalizeKey
@appendToKey
sta gKey,x
inx
bpl @gatherKey
@finalizeKey
stx gKeyLen
cmp #$0D
beq @storeInOKVS
ldx #$00 ; now X = index into the current value
@gatherValue
jsr IncAndGetChar
cmp #$0D ; CR -> finalize value
beq @finalizeValue
sta gVal,x
inx
bpl @gatherValue
@finalizeValue
stx gValLen
@storeInOKVS
tya
pha ; okvs functions clobber everything but we need Y
jsr okvs_append
@store2 !word $FDFD ; SMC
!word gKeyLen
!word gValLen
@maxLength
!byte $FD ; SMC
pla
tay
clc
bcc @newkey ; always branches
@skipLine ; skip to CR
jsr IncAndGetChar
cmp #$0D ; CR
bne @skipLine
beq @newkey ; always branches
;------------------------------------------------------------------------------
; IncAndGetChar
;
; in: Y = index into ($FE)
; ($FE) -> buffer
; out: A contains next byte from buffer
; Y incremented
; $FF possibly incremented
;------------------------------------------------------------------------------
IncAndGetChar
iny
bne +
inc $FF
+ lda ($FE),y
.parseKeyValueDone
rts