;license:MIT ;(c) 2018 by 4am ; ; generic key/value text parser ; ; Public functions: ; - ParseKeyValueList ; gAttractModeStore !word $FDFD gFXStore !word $FDFD gDFXStore !word $FDFD gSlideshowStore !word $FDFD ;------------------------------------------------------------------------------ ; 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