2018-10-23 19:44:06 +00:00
|
|
|
;license:MIT
|
2019-06-24 02:32:18 +00:00
|
|
|
;(c) 2018-9 by 4am
|
2018-10-23 19:44:06 +00:00
|
|
|
;
|
|
|
|
; generic key/value text parser
|
|
|
|
;
|
|
|
|
; Public functions:
|
|
|
|
; - ParseKeyValueList
|
2019-06-30 19:10:09 +00:00
|
|
|
; - IncAndGetChar
|
2018-10-23 19:44:06 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
; 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
|
|
|
|
;
|
2019-10-08 03:20:23 +00:00
|
|
|
; in: stack contains 5 bytes of parameters:
|
2018-10-23 19:44:06 +00:00
|
|
|
; +1 [word] handle to storage space for okvs
|
|
|
|
; +3 [word] handle to buffer containing contents of text file
|
2018-11-10 15:08:14 +00:00
|
|
|
; +5 [byte] max length for okvs records (or 0)
|
2018-10-23 19:44:06 +00:00
|
|
|
; 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
|
2018-11-10 15:08:14 +00:00
|
|
|
+PARAMS_ON_STACK 5
|
2018-10-23 19:44:06 +00:00
|
|
|
|
2021-10-13 22:58:26 +00:00
|
|
|
+LDPARAM 1 ; not LDPARAMPTR, SetKeyPtr requires A/Y!
|
2020-03-24 20:30:14 +00:00
|
|
|
+ST16 @store2
|
2019-09-24 00:01:42 +00:00
|
|
|
jsr SetKeyPtr
|
2018-11-10 15:08:14 +00:00
|
|
|
ldy #5
|
|
|
|
lda (PARAM),y
|
|
|
|
sta @maxLength
|
|
|
|
|
2018-10-23 19:44:06 +00:00
|
|
|
ldy #$00 ; index into ($FE) pointing to current character
|
|
|
|
@newkey ldx #$00 ; X = index into current key
|
2018-10-29 23:23:43 +00:00
|
|
|
stx gValLen ; initialize value length (in case this line has no value)
|
2019-09-24 00:01:42 +00:00
|
|
|
beq @emptyline ; always branches
|
|
|
|
@skipLine ; skip to CR
|
|
|
|
jsr IncAndGetChar
|
2020-03-23 01:58:26 +00:00
|
|
|
cmp #$0A ; CR
|
2019-09-24 00:01:42 +00:00
|
|
|
bne @skipLine
|
|
|
|
@emptyline
|
2018-10-23 19:44:06 +00:00
|
|
|
jsr IncAndGetChar
|
2020-03-23 01:58:26 +00:00
|
|
|
cmp #$0A ; CR in first position (blank line) -> no key
|
2019-09-24 00:01:42 +00:00
|
|
|
beq @emptyline
|
2018-10-23 19:44:06 +00:00
|
|
|
cmp #$23 ; '#' starts a comment -> no key, skip to CR
|
|
|
|
beq @skipLine
|
|
|
|
cmp #$5B ; '[' ends the parsing
|
|
|
|
beq .parseKeyValueDone
|
|
|
|
bne @appendToKey
|
|
|
|
@gatherKey
|
|
|
|
jsr IncAndGetChar
|
2020-03-23 01:58:26 +00:00
|
|
|
cmp #$0A ; CR -> finalize key, no value
|
2018-10-23 19:44:06 +00:00
|
|
|
beq @finalizeKey
|
|
|
|
cmp #$3D ; '=' -> finalize key, start gathering value
|
|
|
|
beq @finalizeKey
|
|
|
|
@appendToKey
|
|
|
|
sta gKey,x
|
|
|
|
inx
|
|
|
|
bpl @gatherKey
|
|
|
|
@finalizeKey
|
|
|
|
stx gKeyLen
|
2020-03-23 01:58:26 +00:00
|
|
|
cmp #$0A
|
2018-10-23 19:44:06 +00:00
|
|
|
beq @storeInOKVS
|
|
|
|
ldx #$00 ; now X = index into the current value
|
|
|
|
@gatherValue
|
|
|
|
jsr IncAndGetChar
|
2020-03-23 01:58:26 +00:00
|
|
|
cmp #$0A ; CR -> finalize value
|
2018-10-23 19:44:06 +00:00
|
|
|
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
|
2018-11-10 15:08:14 +00:00
|
|
|
@maxLength
|
|
|
|
!byte $FD ; SMC
|
2018-10-23 19:44:06 +00:00
|
|
|
pla
|
|
|
|
tay
|
|
|
|
clc
|
|
|
|
bcc @newkey ; always branches
|
|
|
|
|
2019-09-24 00:01:42 +00:00
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
; SetKeyPtr
|
|
|
|
;
|
|
|
|
; in: PARAM set
|
|
|
|
; out: okvs initialised
|
|
|
|
; ($FE) -> buffer
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
SetKeyPtr
|
|
|
|
jsr okvs_init ; reset key/value store
|
|
|
|
|
2019-11-27 21:51:43 +00:00
|
|
|
+LDPARAMPTR 3, $FE
|
2019-09-24 00:01:42 +00:00
|
|
|
|
2019-11-27 21:51:43 +00:00
|
|
|
ldy #0
|
2019-09-24 00:01:42 +00:00
|
|
|
lda ($FE),y
|
|
|
|
tax
|
|
|
|
bne +
|
2019-11-27 21:51:43 +00:00
|
|
|
iny
|
|
|
|
lda ($FE),y
|
|
|
|
sta $FF
|
|
|
|
dec $FF
|
|
|
|
+ dex
|
2019-09-24 00:01:42 +00:00
|
|
|
stx $FE
|
|
|
|
rts
|
2018-10-23 19:44:06 +00:00
|
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
; 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
|
2020-03-23 16:38:27 +00:00
|
|
|
cmp #$0D ; CR - hide it
|
|
|
|
beq IncAndGetChar
|
2018-10-23 19:44:06 +00:00
|
|
|
.parseKeyValueDone
|
|
|
|
rts
|
2021-10-23 04:53:23 +00:00
|
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
; okvs_append
|
|
|
|
;
|
|
|
|
; in: stack contains 7 bytes of parameters:
|
|
|
|
; +1 [word] handle to storage space
|
|
|
|
; +3 [word] address of key
|
|
|
|
; +5 [word] address of value
|
|
|
|
; +7 [byte] maximum length of value (or 0 to fit)
|
|
|
|
; out: (new record count is not returned because no one cares)
|
|
|
|
; all registers clobbered
|
|
|
|
; $00/$01 clobbered
|
|
|
|
; $02/$03 clobbered
|
|
|
|
; $04/$05 has the address of the next available byte after the new record
|
|
|
|
; $08/$09 clobbered
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
okvs_append
|
|
|
|
+PARAMS_ON_STACK 7
|
|
|
|
jsr GetStoreAddress
|
|
|
|
; PTR -> store
|
|
|
|
; Y = 0
|
|
|
|
lda (PTR),y ; A = number of keys in store
|
|
|
|
sta WINDEX
|
|
|
|
iny
|
|
|
|
lda (PTR), y
|
|
|
|
sta WINDEX+1
|
|
|
|
inc WINDEX
|
|
|
|
bne +
|
|
|
|
inc WINDEX+1
|
|
|
|
+
|
|
|
|
dey
|
|
|
|
lda WINDEX
|
|
|
|
sta (PTR),y ; increment number of keys
|
|
|
|
lda WINDEX+1
|
|
|
|
iny
|
|
|
|
sta (PTR),y
|
|
|
|
iny
|
|
|
|
lda (PTR),y ; get address of next free space
|
|
|
|
tax
|
|
|
|
iny
|
|
|
|
lda (PTR),y
|
|
|
|
sta PTR+1
|
|
|
|
sta SAVE+1
|
|
|
|
stx PTR
|
|
|
|
stx SAVE
|
|
|
|
; PTR -> new record
|
|
|
|
; SAVE -> new record
|
|
|
|
jsr incptr
|
|
|
|
; PTR -> space for new key
|
|
|
|
+LDPARAMPTR 3, SRC ; SRC -> new key to copy
|
|
|
|
ldy #0
|
|
|
|
lda (SRC),y
|
|
|
|
tay
|
|
|
|
tax
|
|
|
|
- lda (SRC),y ; copy new key
|
|
|
|
sta (PTR),y
|
|
|
|
dey
|
|
|
|
cpy #$FF
|
|
|
|
bne -
|
|
|
|
|
|
|
|
;;sec
|
|
|
|
txa
|
|
|
|
adc PTR ; update PTR to byte after copied key
|
|
|
|
sta PTR
|
|
|
|
bcc +
|
|
|
|
inc PTR+1
|
|
|
|
+ ; PTR -> space for new value
|
|
|
|
+LDPARAMPTR 5, SRC ; SRC -> new value to copy
|
|
|
|
iny ;;ldy #7
|
|
|
|
lda (PARAM),y ; get max length of value
|
|
|
|
tax
|
|
|
|
bne +
|
|
|
|
tay
|
|
|
|
lda (SRC),y ; no max, use actual length instead
|
|
|
|
tax
|
|
|
|
+ inx
|
|
|
|
tay
|
|
|
|
- lda (SRC),y
|
|
|
|
sta (PTR),y
|
|
|
|
dey
|
|
|
|
cpy #$FF
|
|
|
|
bne -
|
|
|
|
|
|
|
|
txa
|
|
|
|
clc
|
|
|
|
adc PTR
|
|
|
|
tax
|
|
|
|
lda PTR+1
|
|
|
|
adc #0
|
|
|
|
pha
|
|
|
|
+ jsr GetStoreAddress
|
|
|
|
; PTR -> store
|
|
|
|
pla
|
|
|
|
ldy #3
|
|
|
|
sta (PTR),y ; update next-free-space pointer in head
|
|
|
|
dey
|
|
|
|
txa
|
|
|
|
sta (PTR),y
|
|
|
|
sec
|
|
|
|
sbc SAVE
|
|
|
|
ldy #0
|
|
|
|
sta (SAVE),y ; set record length
|
|
|
|
rts
|