PR#3
PREFIX /A2OSX.SRC
NEW
INC 1
AUTO 6
				.LIST OFF	
				.OP	65C02
				.OR	$2000
				.TF /A2OSX.BOOT/LIB/LIBSTR.O
*--------------------------------------
				.INB INC/MACROS.I
				.INB INC/A2OSX.I
*--------------------------------------
ZPTmpPtr1		.EQ ZPLIB
ZPTmpPtr2		.EQ ZPLIB+2
ZPTmpPtr3		.EQ ZPLIB+4
*--------------------------------------
*			File Header (16 Bytes)
*--------------------------------------
CS.START		cld
				jmp (.1,x)
				.DA #$61				6502,Level 1 (65c02)
				.DA #1					BIN Layout Version 1
				.DA 0
				.DA CS.END-CS.START
				.DA 0
				.DA 0
				.DA 0
*--------------------------------------
* Relocation Table
*--------------------------------------
.1				.DA LIB.LOAD
				.DA LIB.UNLOAD
				.DA PrintF
				.DA PrintC
				.DA PrintP
				.DA STRMATCHP
				.DA STRCPYP
				.DA STRCATP
				.DA UCASEP
				.DA LCASEP
				.DA	PrintDATE
				.DA	PrintTIME
				.DA SSCANF
*--------------------------------------
PrintFJMP1		.DA	PrintFA
				.DA	PrintFB,PrintFBB
				.DA	PrintFD,PrintFDD,PrintFL
				.DA	PrintFE,PrintFEE
				.DA	PrintFH,PrintFHH
				.DA	PrintFI,PrintFII
				.DA	PrintFSC,PrintFSP
				.DA	PrintFT,PrintFTT
PrintFJMP2		.DA	PrintFESC,PrintFCR,PrintFBKSLH,PrintFPERCENT
*--------------------------------------
				.DA 0
*--------------------------------------
LIB.LOAD
LIB.UNLOAD		clc
				rts
*--------------------------------------
* PrintF :
* Prints C-Style String
* PULLW Pointer to Sting,Last Byte negative 
* %a pull 1 byte to Print ATTRIB String
* %b pull 1 byte to Print BIN
* %B pull 2 byte to Print BIN
* %d pull 1 byte to Print unsigned DEC
* %D pull 2 bytes to Print unsigned DEC
* %L pull 4 bytes to Print unsigned DEC
* %n pull 1 byte to Print low Nibble HEX
* %N pull 1 byte to Print high Nibble HEX
* %h pull 1 byte to Print HEX
* %H pull 2 bytes to Print HEX
* %i pull 1 byte to Print signed DEC
* %I pull 2 bytes to Print signed DEC
* %s pull 2 bytes ptr to C-Style String
* %S pull 2 bytes ptr to P-Style String
* \e Print 'ESC' ($1B,27)
* \n Print CR=13
* \\ Print \
* \% Print %
* padding : 
*   %d	   '9'  '12'
*   %2d	   ' 9' '12'   				
*	%02d   '09' '12'
*	%16s   'ABCDEFGHIjkl   '	
*	%011s  'ABCDEFGH000'	
*--------------------------------------
PrintF			>PULLW ZPTmpPtr1
				ldy	#0
PrintFCOUT		lda (ZPTmpPtr1),y
				beq .1 
				cmp #'%'
				beq PrintFESC1
				cmp #'\'
				beq PrintFESC2
				jsr	COUT
				iny
				bne	PrintFCOUT
.1				rts
PrintFEXIT		ply
				iny
				bne	PrintFCOUT
				rts
*--------------------------------------
PrintFESC1		stz PADLEN
				lda #' '
				sta PADCHAR
.1				ldx	#PrintFTBL1.END-PrintFTBL1-1
				iny
				lda	(ZPTmpPtr1),y
				beq .9
.2				cmp PrintFTBL1,x		do we have a %x command?
				beq .8					yes, jmp to it!
				dex
				bpl	.2					no valid letter...
				cmp #'0'				...a 0...mmm... padding char!!
				beq .4
				bcc .9					
				cmp #'9'
				bcs .9					
.3				and #$0F				we have a digit
				pha						save it...
				lda PADLEN				starts PADLEN * 10
				asl						times 2
				pha						save times 2
				asl						times 4
				asl						times 8
				sta PADLEN
				pla						get back times 2
				clc
				adc PADLEN				times 8 + times 2 = times 10
				sta PADLEN
				pla						get back current digit
				adc PADLEN
				sta PADLEN
				bra .5
.4				lda PADLEN				do we already had met digits to build PADLEN ?
				bne .3					yes, continue to build PADLEN
				lda #'0'
				sta PADCHAR				no, this is the first 0, so make it PADCHAR
.5				bra .1
.8				phy
				txa
				asl
				tax
				jmp	(PrintFJMP1,x)
.9				rts
*--------------------------------------
PrintFESC2		ldx	#PrintFTBL2.END-PrintFTBL2-1
				iny
				lda	(ZPTmpPtr1),y
				beq .9
.2				cmp PrintFTBL2,x
				beq .3
				dex
				bpl	.2
				rts
.3				phy
				txa
				asl
				tax
				jmp	(PrintFJMP2,x)
.9				rts				
*--------------------------------------
PrintFA			>PULLA
				ldx #0
.1				asl
				pha
				lda #'-'
				bcc .2
				lda PrintF.ATTRIB,x
.2				jsr COUT
				pla
				inx
				cpx #8		
				bne .1
				jmp	PrintFEXIT
PrintFB			ldx #8
				>PULLA
.1				asl
				pha
				lda #'0'
				bcc .2
				inc
.2				jsr COUT
				pla
				dex
				bne .1
				jmp	PrintFEXIT
PrintFBB		>PULLA
				>PULLA
				jmp	PrintFEXIT
PrintFD			>PULLA
				sta HEXBUF
				stz HEXBUF+1
				stz HEXBUF+2
				stz HEXBUF+3
				jsr HEX2DEC
				jmp	PrintFEXIT
PrintFDD		>PULLA
				sta HEXBUF
				>PULLA
				sta HEXBUF+1
				stz HEXBUF+2
				stz HEXBUF+3
				jsr HEX2DEC
				jmp	PrintFEXIT
PrintFL			>PULLA
				sta HEXBUF
				>PULLA
				sta HEXBUF+1
				>PULLA
				sta HEXBUF+2
				>PULLA
				sta HEXBUF+3
				jsr HEX2DEC
				jmp	PrintFEXIT
PrintFE			>PULLA
				jsr PRHEX
				jmp	PrintFEXIT
PrintFEE		>PULLA
				lsr
				lsr
				lsr
				lsr
				jsr PRHEX
				jmp	PrintFEXIT
PrintFH			>PULLA
				jsr	PRBYTE
				jmp PrintFEXIT
PrintFHH		>PULLA
				pha
				>PULLA
				jsr	PRBYTE
				pla
				jsr	PRBYTE
				jmp PrintFEXIT
PrintFI			>PULLA
				jmp	PrintFEXIT
PrintFII		>PULLA
				>PULLA
				jmp	PrintFEXIT
PrintFSC		>PULLYA
				jsr PrintYA
				jmp	PrintFEXIT
PrintFSP		>PULLYA
				jsr PrintYAP
				jmp	PrintFEXIT
PrintFT			jsr PrintTIME
				jmp	PrintFEXIT
PrintFTT		jsr PrintDATE
				jmp	PrintFEXIT		
*--------------------------------------
PrintFESC		lda #$1B				ESC
				jsr COUT
				jmp	PrintFEXIT
PrintFCR		jsr CROUT
				jmp	PrintFEXIT
PrintFBKSLH		lda #'\'
				jsr COUT
				jmp	PrintFEXIT
PrintFPERCENT	lda #'%'
				jsr COUT
				jmp	PrintFEXIT
*--------------------------------------
PrintC			>PULLW ZPTmpPtr2
				ldy	#0
.1				lda	(ZPTmpPtr2),y
				beq .8
				jsr COUT
				iny
				bne .1
.8				rts	
*--------------------------------------
PrintP			>PULLW ZPTmpPtr2
				ldy	#0
				lda	(ZPTmpPtr2),y
				tax
				beq .8
.1				iny
				lda	(ZPTmpPtr2),y
				jsr COUT
				dex
				bne .1
.8				rts
*--------------------------------------
* STRMATCHP : (P-Style Strings)
* pull PTR to Dest String
* pull PTR to Src string
* works with wildcards :
* Dest Str      Src str
* message   =   m?ss*
*			= 	me*ge 
*			= 	*ge
*			=	*
* message   =   me?sage != me?age
*--------------------------------------
STRMATCHP		>PULLW ZPTmpPtr1
				>PULLW ZPTmpPtr2
				rts
*--------------------------------------
* STRCPYP : (P-Style Strings)
* pull PTR to Dest String
* pull PTR to Src string
*--------------------------------------
STRCPYP			>PULLW ZPTmpPtr1
				>PULLW ZPTmpPtr2
				lda	(ZPTmpPtr2)
				sta	(ZPTmpPtr1)
				tay
				beq .2
.1				lda	(ZPTmpPtr2),y
				sta	(ZPTmpPtr1),y
				dey
				bne .1
.2				rts
*--------------------------------------
* STRCATP : (P-Style Strings)
* pull PTR to Dest String
* pull PTR to Src string
*--------------------------------------
STRCATP			>PULLW ZPTmpPtr1
				>PULLW ZPTmpPtr2
				lda	(ZPTmpPtr1)
				tay
				iny
				lda	(ZPTmpPtr2)
				tax
				beq .3
.1				inc ZPTmpPtr2
				bne .2
				inc ZPTmpPtr2+1
.2				lda	(ZPTmpPtr2)
				sta	(ZPTmpPtr1),y
				iny
				dex
				bne .1
				dey
				tya
				sta	(ZPTmpPtr1)
.3				rts
*--------------------------------------
UCASEP			phx
				>PULLW ZPTmpPtr2
				ldy	#0
				lda	(ZPTmpPtr2),y
				tax
				beq .9
.1				iny
				lda	(ZPTmpPtr2),y
				cmp #'a'
				bmi .2
				cmp #'z'+1
				bpl .2
				sec
				sbc #$20
				sta	(ZPTmpPtr2),y
.2				dex
				bne .1
.9				plx
				rts	
*--------------------------------------
LCASEP			phx
				>PULLW ZPTmpPtr2
				ldy	#0
				lda	(ZPTmpPtr2),y
				tax
				beq .9
.1				iny
				lda	(ZPTmpPtr2),y
				cmp #'A'
				bmi .2
				cmp #'Z'+1
				bpl .2
				clc
				adc #$20
				sta	(ZPTmpPtr2),y
.2				dex
				bne .1
.9				plx
				rts	
*--------------------------------------
* PULLW = DATE in ProDOS Format
* A = year, Y = month/day
*--------------------------------------
PrintDATE		stz HEXBUF+1
				stz HEXBUF+2
				stz HEXBUF+3
				ldx #'0'
				stx PADCHAR
				ldx #2
				stx PADLEN
				>PULLYA
				pha						save year to get high bit of month later
				lsr
				pha
				cmp #70					are we in the 70s ?
				bcc .1
				lda #$19
				bra .2
.1				lda #$20
.2				jsr PRBYTE
				pla
				sta HEXBUF
				jsr HEX2DEC
				lda #'/'
				jsr COUT
				ldx #'0'
				stx PADCHAR
				ldx #2
				stx PADLEN
				pla						get back year
				lsr						get high bit of month in carry
				tya						get month/day
				pha						save it for day
				ror						pick high bit from carry
				lsr
				lsr
				lsr
				lsr
				sta HEXBUF
				jsr HEX2DEC
				lda #'/'
				jsr COUT
				ldx #'0'
				stx PADCHAR
				ldx #2
				stx PADLEN
				pla						get back  month/day
				and #$1F
				sta HEXBUF
				jmp HEX2DEC
*--------------------------------------
* PULLW = TIME in ProDOS Format
* A = hours, Y = minutes
*--------------------------------------
PrintTIME		stz HEXBUF+1
				stz HEXBUF+2
				stz HEXBUF+3
				ldx #'0'
				stx PADCHAR
				ldx #2
				stx PADLEN
				>PULLYA
				and #$1F
				sta HEXBUF
				jsr HEX2DEC
				lda #':'
				jsr COUT
				ldx #'0'
				stx PADCHAR
				ldx #2
				stx PADLEN
				tya						get minutes
				and #$3F
				sta HEXBUF
				jmp HEX2DEC
*--------------------------------------
*
*--------------------------------------
SSCANF			>PULLW ZPTmpPtr1		get PString to scan (ex: "192.168.1.5")
				>PULLW ZPTmpPtr2		get PString pattern	(ex: "%d.%d.%d.%d")
				>PULLW ZPTmpPtr3		get target buffer
				
				ldy	#0					Y = PTR in pattern
				
				lda (ZPTmpPtr1)
				beq .9
				tax						X = COUNT to scan
				inc ZPTmpPtr1
				bne .1
				inc ZPTmpPtr1+1

.1				txa						End Of String?
				beq .8
				tya
				cmp (ZPTmpPtr2)			End of pattern?
				beq .8
				iny
				lda (ZPTmpPtr2),y
				cmp #'%' 				Escape?
				beq .2
				cmp (ZPTmpPtr1)			Same char?
				bne .9
				jsr SSCANF.IncPtr1
				bne .1
				clc
				rts
				
.2				tya 
				cmp (ZPTmpPtr2)			unexpected End of pattern after "%" ?
				beq .9

				iny
				lda (ZPTmpPtr2),y
				cmp #'d'				BYTE ?
				bne .3
				
				stz ASCBUF
.20				lda (ZPTmpPtr1)
				jsr SSCANF.IsDigit
				bcs .21
				phx
				inc ASCBUF
				ldx ASCBUF
				sta ASCBUF,x
				plx
				jsr SSCANF.IncPtr1
				bne .20					end of string ?
				
.21				jsr DEC2HEX
				lda HEXBUF
				sta (ZPTmpPtr3)
				inc ZPTmpPtr3
				bne .1
				inc ZPTmpPtr3+1
				bra .1

.3				cmp #'D'				WORD ?
				bne .4
				
				bra .1

.4				cmp #'s'				STRING ?
				bne .9
				
				bra .1
				
.8				clc
				rts
				
.9				sec
				rts

*--------------------------------------
SSCANF.IncPtr1	dex
				beq .1
				inc ZPTmpPtr1
				bne .1
				inc ZPTmpPtr1+1			never Zero
.1				rts
*--------------------------------------
SSCANF.IsDigit	cmp #'0'
				bcc .1
				cmp #'9'+1
				bcs .1
				rts
.1				sec
				rts				
*--------------------------------------
********** PRIVATE FUNCTIONS **********
*--------------------------------------
* PrintYAC : 
* Prints C-Style String
* Y,A=Pointer to Sting, Last Byte 0 
*--------------------------------------
PrintYA			>STYA ZPTmpPtr2
				ldy	#0
.1				lda	(ZPTmpPtr2),y
				beq .2
				jsr COUT
				iny
				bne .1
.2				rts	
*--------------------------------------
* PrintYAP :
* Prints Pascal-Style String
* Y,A=Pointer to Sting, LEN=1st Byte 
*--------------------------------------
PrintYAP		phx
				>STYA ZPTmpPtr2
				ldy	#0
				lda	(ZPTmpPtr2),y
				tax
				beq .8
.1				iny
				lda	(ZPTmpPtr2),y
				jsr COUT
				lda PADLEN
				beq .2
				cpy	PADLEN
				beq .8
.2				dex
				bne .1
				lda PADLEN
				beq .8
.3				lda PADCHAR				
				jsr COUT
				iny
				cpy PADLEN
				bne .3
.8				plx
				rts
*--------------------------------------
* Convert HEXBUF to ASCBUF decimal padded with 0
*--------------------------------------
HEX2DEC			phx
				phy
				ldx #4
.1				stz BCDBUF,x	Clear all 5 bytes
				dex
				bpl .1
				ldx #32			let's roll 32 bits
				sed
.2				asl HEXBUF
				rol	HEXBUF+1
				rol HEXBUF+2
				rol HEXBUF+3
				php				cpy will disturb carry while BCD adc
				ldy #0
.3				plp
				lda BCDBUF,y
				adc BCDBUF,y
				sta BCDBUF,y
				php
				iny
				cpy #5			Last byte of BCDBUF?
				bne .3
				plp
				dex
				bne .2
				cld
				ldy #0
				ldx #9
.4				lda BCDBUF,y
				pha
				and #$0F
				ora #$30
				sta	ASCBUF,x
				dex
				pla
				lsr
				lsr
				lsr
				lsr
				ora #$30
				sta	ASCBUF,x
				iny
				dex
				bpl .4
				lda PADLEN			any Len format ?
				beq .5				no
				lda #10
				sec					yes, Print only digits starting at pos 10-padlen
				sbc PADLEN
.5				tax					x=0 if no padlen, or x=10-padlen
.6				lda ASCBUF,x		
				cmp #'0'			a zero?
				beq .7
				inc PADLEN			found a non zero, Print all digits, even if 0, next time
				ldy #'0'
				sty PADCHAR
				bra .8
.7				cpx #9				last digit ?
				beq .8				Print always
				ldy PADLEN			no pad to fill, do not Print 0
				beq .9
				lda PADCHAR			fill with PADCHAR
.8				jsr COUT
.9				inx
				cpx #10
				bne .6
				ply
				plx
				rts
*--------------------------------------
* Convert ASCBUF decimal to HEXBUF
*--------------------------------------
DEC2HEX			phx
				phy
				stz HEXBUF
				stz HEXBUF+1
				stz HEXBUF+2
				stz HEXBUF+3
				
				ldx #0
.1				asl HEXBUF				HEXBUF * 2 -> HEXBUF
				rol HEXBUF+1
				rol HEXBUF+2
				rol HEXBUF+3

				lda HEXBUF				HEXBUF * 2 -> HEXBUFTMP
				asl
				sta HEXBUFTMP
				lda HEXBUF+1
				rol
				sta HEXBUFTMP+1
				lda HEXBUF+2
				rol
				sta HEXBUFTMP+2
				lda HEXBUF+3
				rol
				sta HEXBUFTMP+3

				asl HEXBUFTMP			HEXBUFTMP * 2 -> HEXBUFTMP
				rol HEXBUFTMP+1
				rol HEXBUFTMP+2
				rol HEXBUFTMP+3

				lda HEXBUF				HEXBUF + HEXBUFTMP -> HEXBUF
				clc
				adc HEXBUFTMP
				sta HEXBUF
				lda HEXBUF+1
				adc HEXBUFTMP+1
				sta HEXBUF+1
				lda HEXBUF+2
				adc HEXBUFTMP+2
				sta HEXBUF+2
				lda HEXBUF+3
				adc HEXBUFTMP+3
				sta HEXBUF+3

				inx
				lda ASCBUF,x
				and #$0F
				clc
				adc HEXBUF
				sta HEXBUF
				bcc .2
				inc HEXBUF+1
				bne .2
				inc HEXBUF+2
				bne .2
				inc HEXBUF+3
.2				cpx ASCBUF
				bne .1
				ply
				plx
				rts
*--------------------------------------
PRBYTE			pha
				lsr
				lsr
				lsr
				lsr
				ora #$30
				cmp #'9'+1
				bcc .1
				adc #6
.1				jsr COUT
				pla
PRHEX			and #$0F
				ora #$30
				cmp #'9'+1
				bcc COUT
				adc #6
				bra COUT
*--------------------------------------
CROUT			lda #13	
*--------------------------------------
COUT			phx
				phy
				cmp #13
				bne .1
				ldx #DEVMGR.COUT
				jsr pDevJmp
				bcs .9
				lda #10
				
.1				ldx #DEVMGR.COUT
				jsr pDevJmp
				ply
				plx
.9				rts
*--------------------------------------
CS.END
PrintFTBL1		.AS	"abBdDLnNhHiIsStT"
PrintFTBL1.END
PrintFTBL2		.AS	"en\%"
PrintFTBL2.END
PrintF.ATTRIB	.AS "dnb+++wr"
*--------------------------------------
PADCHAR			.BS 1
PADLEN			.BS 1
HEXBUF			.BS 4					32 bits max
HEXBUFTMP		.BS 4
BCDBUF			.BS 5					5, enough to handle 32bits
ASCBUF			.BS 11					LEN + 10 digits ($FFFFFFFF=4.294.967.295)
*--------------------------------------
MAN
SAVE LIB/LIBSTR.S
ASM
