;*******************************************************************************
;* Program   : TRIM.SUB
;* Programmer: Tony Papadimitriou <tonyp@acm.org>
;* Purpose   : Trim function for ASCIZ string
;* Language  : Freescale HC08/9S08 Assembly Language (aspisys.com/ASM8 v9.69+)
;* Status    : FREEWARE Copyright (c) 2016 by Tony Papadimitriou <tonyp@acm.org>
;* Original  : http://www.aspisys.com/code/hc08/trim.html
;* History   : 09.08.11 v1.00 Original (Verified for correctness)
;*           : 10.04.03       Made use of #SPAUTO
;*           : 11.04.10       Moved test code at EOF (for #EXIT optimization)
;*           : 11.10.03 v1.01 BugFix: StringTrim did not return updated length
;*           : 13.09.05 v1.10 Added StringTrimLeading & StringTrimTrailing
;*******************************************************************************

#ifmain ;-----------------------------------------------------------------------
                    #ListOff
                    #Uses     mcu.inc
                    #ListOn
                    #MapOff
#endif ;------------------------------------------------------------------------
?_OBJECT_?

#ifnomdef StringDeleteChar
StringDeleteChar    macro     [[#]String]
          #ifb ~@~
                    call      ~0~
                    mexit
          #endif
                    #push
                    #spauto   :sp
                    pshhx
                    @@lea     ~@~
                    call      ~0~
                    pulhx
                    #pull
                    endm
#endif

;*******************************************************************************

#ifndef StringTrim
;*******************************************************************************
; Purpose: Trim string from leading, trailing, and duplicate in-between spaces
; Input  : HX -> ASCIZ string
; Output : A = Length of updated string
; Note(s):
                    #spauto

StringTrim          proc
                    clra                          ;character position
                    push      :temp
                    next      :temp,2
pos@@               next      :temp

                    bra       Loop@@

Delete@@            lda       pos@@,sp
                    cbeqa     #1,DeleteNow@@      ;if at 1st position, delete

                    tst       1,x                 ;if at last position, delete
                    beq       DeleteNow@@

                    lda       -1,x                ;load previous character
                    cmpa      #' '                ;if previous not a space
                    bne       Skip@@              ; skip deleting

DeleteNow@@         @StringDeleteChar             ;HX -> 1st string position
                    dbnz      pos@@,sp,Previous@@

Loop@@              lda       ,x
                    beq       Done@@              ;end of string, exit

                    inc       pos@@,sp            ;increment character position
                    cbeqa     #' ',Delete@@

Skip@@              aix       #1                  ;skip non-blank
                    bra       Loop@@

Previous@@          aix       #-1
                    dec       pos@@,sp            ;decrement character position
                    bra       Loop@@

Done@@              pull
                    rtc
#endif

;*******************************************************************************
; Purpose: Trim leading spaces (head of string)
; Input  : HX -> ASCIZ (sub-)string
; Output : None
; Note(s):
                    #spauto   :ab

StringTrimHead      proc
                    psha

                    lda       #' '                ;will be looking for spaces
Loop@@              cmpa      ,x                  ;is first string char a space?
                    bne       Done@@              ;no, we're done
                    @StringDeleteChar             ;else, delete this char
                    bra       Loop@@              ;repeat

Done@@              pula
                    rtc

;*******************************************************************************
; Purpose: Trim trailing spaces (tail of string)
; Input  : HX -> ASCIZ (sub-)string
; Output : None
; Note(s):
                    #spauto   :ab

StringTrimTail      proc
                    push

                    @SkipChar #0                  ;go past end of string
                    aix       #-1                 ;back up one to -> null

                    lda       #' '                ;will be looking for spaces
Loop@@              aix       #-1                 ;back up one
                    cmpa      ,x                  ;is last string char a space?
                    bne       Done@@              ;no, we're done
                    @StringDeleteChar             ;else, delete this char
                    bra       Loop@@              ;repeat

Done@@              pull
                    rtc

#ifndef StringDeleteChar
;*******************************************************************************
; Purpose: Delete first character in ASCIZ (sub-)string
; Input  : HX -> ASCIZ (sub-)string
; Output : None
; Note(s):
                    #spauto   :ab

StringDeleteChar    proc
                    push

                    tst       ,x
Loop@@              beq       Done@@
                    lda       1,x
                    sta       ,x
                    aix       #1
                    bra       Loop@@

Done@@              pull
                    rtc
#endif
                    #sp
;*******************************************************************************
                    #Exit
;*******************************************************************************
                    @EndStats

                    #Uses     lib/copy.sub

                    #MapOn

Start               proc
                    @rsp
                    clra

                    ldhx      #StrVar

                    bsr       Restore
                    call      StringTrim

                    bsr       Restore
                    call      StringTrimHead

                    bsr       Restore
                    call      StringTrimTail

                    bra       *

                    #MapOff

Restore             proc
                    @Copy     #String@@ #StrVar #::String@@
                    rts

String@@            fcs       '  Trim  leading,   trailing,   and    any    multiple    in-between spaces!            '

StrVar              @var      ::String@@

                    @vector   Vreset,Start