pitch-dark/src/parse.common.a

128 lines
3.9 KiB
Plaintext

;license:MIT
;(c) 2018 by 4am
;
; Common functions across parsers
;
; Public functions:
; - ParseKeyValueText
; - IncAndGetChar
;
;------------------------------------------------------------------------------
; ParseKeyValueText
; parse buffer with KEY=VALUE lines of text into an okvs
; keys and values limited to 127 characters, which should be enough for anyone
;
; in: stack contains 5 bytes of parameters:
; +1 [word] handle to storage space
; +3 [word] handle to data buffer
; +5 [byte] max length for okvs records (or 0)
; out: all registers and flags clobbered
; $3F00..$3FFF clobbered
; $00/$01 clobbered
; $02/$03 clobbered
; $04/$05 has the address of the next available byte after the okvs
; $FE/$FF clobbered
;------------------------------------------------------------------------------
ParseKeyValueText
+PARAMS_ON_STACK 5
+LDPARAM 1
+STAY @store1
+STAY @store2
+LDPARAM 3
+STAY $FE
ldy #5
lda (PARAM),y
sta @maxLength
lda ($FE)
pha
ldy #1
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
@gatherKey
jsr IncAndGetChar
and #$7F ; keys get their high bit stripped
cmp #$23 ; '#' is starts a comment (until CR)
beq @skipComment
cmp #$3D ; '=' ends the key
beq @endKey
cmp #$0D ; found CR before '=', ignore key and start over (also handles blank lines)
beq @newkey
cmp #$5B ; '[' ends the parsing
beq .parseKeyValueDone
sta gKey,x
inx
bpl @gatherKey
@endKey stx gKeyLen
ldx #$00 ; now X = index into the current value
@gatherValue
jsr IncAndGetChar ; note: values do NOT get their high bit stripped
cmp #$0D ; CR ends the value
beq @endValue
cmp #$00 ; null also ends the value
beq @endValue
sta gVal,x
inx
bpl @gatherValue
@endValue
stx gValLen
cpx #1
bne @useMaxLength
lda gVal
and #1
sta gVal ; single-character values get converted to #$00 or #$01 in prefs store
lda #0
+HIDE_NEXT_2_BYTES
@useMaxLength
@maxLength=*+1
lda #$FD ; SMC
sta @appendMaxLength ; all other values get upgraded to max_length so we can update them in place
phy ; okvs functions clobber everything but we need Y
jsr okvs_append
@store2 !word $FDFD ; SMC
!word gKeyLen
!word gValLen
@appendMaxLength
!byte $FD ; SMC
ply
bra @newkey
@skipComment ; skip to CR
jsr IncAndGetChar
cmp #$0D ; CR
bne @skipComment
bra @newkey
;------------------------------------------------------------------------------
; 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