NEW
  AUTO 3,1
*/--------------------------------------
* # fputc (BLOCKING)
* Print A (char) to hFILE
* ## C
* `int fputc ( hFILE stream , short int character );`
* ## ASM
* `>PUSHB stream`
* `>PUSHB character`
* `>SYSCALL fputc`
* ## RETURN VALUE
* CC = success
*\--------------------------------------
K.FPutC			lda (pStack)			character
				sta K.IOBuf

				ldy #1
				lda (pStack),y			hFile
				>PUSHA

				jsr STDIO.Put1
				bcc .8

				tay
				beq .9					BLOCKING, keep parms on stack

.8				>POP 2

.9				rts
*/--------------------------------------
* # putchar (BLOCKING)
* Print A (char) to StdOut
* ## C
* `int putchar ( short int character );`
* ## ASM
* `lda character`
* `>SYSCALL putchar`
* ## RETURN VALUE
* CC = success
*\--------------------------------------
K.PutChar		sta K.IOBuf				character

				ldy #S.PS.hStdOut
				lda	(pPS),y
				>PUSHA
*--------------------------------------
STDIO.Put1		>PUSHWI K.IOBuf			buf

				lda #0
				>PUSHA
				inc						write 1 byte
				>PUSHA

STDIO.Write		jsr K.FWrite.PFT
				bcc .9

				tay
				bne .9

				>POP 5

.9				rts
*/--------------------------------------
* # puts (BLOCKING)
* Write Str to StdOut, appends '\r\n'
* ## C
* `int puts ( const char * str );`
* ## ASM
* `>LDYAI str`
* `>SYSCALL PutS`
* ## RETURN VALUE
* CC = success
*\--------------------------------------
K.PutS			>STYA .1+1

				ldx #0

.1				lda $FFFF,x				SELF MODIFIED
				beq .2

				sta K.IOBuf,x
				inx
				bne .1

.9				lda #E.BUF
				sec
				rts

.2				lda #C.CR
				sta K.IOBuf,x
				inx
				beq .9

				lda #C.LF
				sta K.IOBuf,x
				inx
				beq .9

				ldy #S.PS.hStdOut
				lda	(pPS),y
				>PUSHA
				>PUSHWI K.IOBuf
				>PUSHBI 0
				txa
				>PUSHA

				bra STDIO.Write
*/--------------------------------------
* # fputs (BLOCKING)
* Write Str to hFILE
* ## C
* `int fputs (hFILE stream, const char * str );`
* ## ASM
* `>PUSHB stream`
* `>PUSHW str`
* `>SYSCALL fputs`
* ## RETURN VALUE
* CC = success
*\--------------------------------------
K.FPutS			lda (pStack)
				sta ZPPtr1				Get String
				sta ZPPtr2

				ldy #1
				lda (pStack),y
				sta ZPPtr1+1
				sta ZPPtr2+1

				ldy #0
				ldx #0

.1				lda (ZPPtr1),y
				beq .2

				iny
				bne .1

				inx
				inc ZPPtr1+1
				bra .1

.2				phy

				ldy #2
				lda (pStack),y
				>PUSHA

				>PUSHW ZPPtr2

				txa
				>PUSHA					push len HI

				pla
				>PUSHA					push len LO

				jsr STDIO.Write
				bcs .9

				>POP 3

.9				rts
*/--------------------------------------
* # fgets (BLOCKING)
* read bytes from stream into the array
* pointed to by s, until n-1 bytes are read, or a <newline> is read and
* transferred to s, or an end-of-file condition is encountered. The
* string is then terminated with a null byte.
* ## C
* `char *fgets(hFILE stream, char * s, int n);`
* ## ASM
* `>PUSHB hFILE`
* `>PUSHW s`
* `>PUSHW n`
* `>SYSCALL fgets`
* ## RETURN VALUE
*  Y,A: s
* CC = success
*\--------------------------------------
* (pStack)+4	h
* (pStack)+2	s -> ZPPtr2
* (pStack)+0	n -> ZPPtr1
*--------------------------------------
K.FGetS			ldy #3

.1				lda (pStack),y
				sta ZPPtr1,y
				dey
				bpl .1

				lda ZPPtr1+1
				bmi .4					already something in buffer

.2				ldy #4
				lda (pStack),y
				jsr STDIO.Get1
				bcs .9

*				BLOCKING > POP 5 FREAD parms
*				EOF or IOERR.... > POP 5 FGETS parms

.3				lda K.IOBuf
				cmp #C.LF				Discard any leading LF from a prev CR/LF
				beq .2

				clc						set n = !n + 1
				lda ZPPtr1
				eor #$ff
				adc #1
				sta ZPPtr1

				lda ZPPtr1+1
				eor #$ff
				adc #0
				sta ZPPtr1+1

				bra .5
*--------------------------------------
.4				ldy #4
				lda (pStack),y
				jsr STDIO.Get1
				bcs .6

.5				lda K.IOBuf
				cmp #C.CR
				beq .8

				jsr SHARED.PutCP2

				inc ZPPtr1
				bne .4

				inc ZPPtr1+1
				bne .4

				beq .8					Buffer full

.6				tay
				beq .70

				cmp #MLI.E.EOF
				beq .8					String terminated by EOF

				bra .9					I/O error > POP 5 FGETS parms

.70				jsr .9					> POP 5 FREAD parms

				ldy #3

.7				lda ZPPtr1,y			NO DATA, but string not yet terminated
				sta (pStack),y
				dey
				bpl .7

				lda #0					BLOCKING
*				sec
				rts

.8				lda #0
				sta (ZPPtr2)			terminate string
				tay						return NULL (TODO: return s)
				clc
.9				>RET 5
*/--------------------------------------
* # getchar (BLOCKING)
* Get char from StdIn
* ## C
* `short int getchar ( );`
* ## ASM
* `>SYSCALL getchar`
* ## RETURN VALUE
*  CC = success
*   A = char
*\--------------------------------------
K.GetChar		ldy #S.PS.hStdIn
				lda	(pPS),y
*/--------------------------------------
* # getc (BLOCKING)
* Get char from Node
* ## C
* `short int getc ( short int stream );`
* ## ASM
* `lda stream`
* `>SYSCALL getc`
* ## RETURN VALUE
*  CC = success
*   A = char
*\--------------------------------------
K.GetC			jsr STDIO.Get1
				bcc .8

				tay
				bne .9					I/O error

				>POP 5					BLOCKING
				rts

.8				lda K.IOBuf

.9				rts
*--------------------------------------
STDIO.Get1		>PUSHA

				>PUSHWI K.IOBuf
				lda #0
				>PUSHA
				inc						read 1 byte
				>PUSHA
				ldx #_FRead
				jmp K.FRead
*/--------------------------------------
* # ungetc
* push byte back into input stream
* ## C
* `short int ungetc(short int c, short int stream);`
* ## ASM
* `>PUSHB c`
* `>PUSHB stream`
* `>SYSCALL ungetc`
* ## RETURN VALUE
*  CC = success
*   A = char
*\--------------------------------------
K.UngetC		clc
				rts
*/--------------------------------------
* # FOpen
* Open a file
* ## C
* `short int fopen ( const char *filename, short int flags, short int ftype, int auxtype );`
* ## ASM
* `>PUSHW filename`
* `>PUSHB flags`
*  + O.RDONLY : if R and !exists -> ERROR
*  + O.WRONLY : if W and !exists -> CREATE
*  + O.TRUNC : Reset Size To 0
*  + O.APPEND : Append
*  + O.TEXT   : Open/Append in Text mode
*  + O.CREATE : Create if not exists
* `>PUSHB ftype`
* `>PUSHW auxtype`
* TODO: replace flags/ftype/auxtype with mode="w+,t=TYP,x=AUXTYPE"
*  + r  = O_RDONLY
*  + r+ = O_RDWR
*  + w  = O_WRONLY | O_CREAT | O_TRUNC
*  + w+ = O_RDWR | O_CREAT | O_TRUNC
*  + a  = O_WRONLY | O_CREAT | O_APPEND
*  + a+ = O_RDWR | O_CREAT | O_APPEND
*  + ,t=123 or t=$ff or t=TXT
*  + ,x=12345 or x=$ffff
* ## RETURN VALUE
*  CC : A = hFILE
*  CS : A = EC
*\--------------------------------------
K.FOpen			jsr PFT.CheckPath4
				bcs K.FOpen.9

				>PULLW IO.Open.AUXTYPE
				>PULLB IO.Open.TYPE
				>PULLB IO.Open.FLAGS

				inc pStack				discard filename
				inc pStack

				jsr UNISTD.Open
				bcs K.FOpen.99

				lda (pFD)
				cmp #S.FD.T.DSOCK
				bcc .1
				
				lda IO.hFILE			don't create file for SOCK/PIPE
				tax
				inc FILEs.oCnt-1,x
				
				clc

				rts

.1				>LDYAI K.Buf256
				>STYA ZPPtr1

K.FOpen.REGDIR	jsr K.MkNod.I
				bcs K.FOpen.90
				
*				tax
				inc FILEs.oCnt-1,x

*				clc

				rts

K.FOpen.90		pha
				jsr UNISTD.Close
				pla
				sec
				rts

K.FOpen.9		>POP 6

K.FOpen.99		rts
*/--------------------------------------
* # FClose
* Close a file
* ## C
* `int fclose ( short int stream );`
* ## ASM
* `lda stream`
* `>SYSCALL FClose`
* ## RETURN VALUE
*\--------------------------------------
K.FClose		jsr PFT.CheckNodeA
				bcs K.FRead.RTS

				jsr UNISTD.Close
				bcs K.FRead.RTS

				ldx IO.hFILE
				dec FILEs.oCnt-1,x

*				clc

				bne K.FRead.RTS

				stz FILEs.hFD-1,x

				lda FILEs.hName-1,x

*				clc

				beq K.FRead.RTS
				
				stz FILEs.hName-1,x
				jmp K.FreeMem
*/--------------------------------------
* # FRead (BLOCKING)
* Read bytes from file
* ## C
* `int fread (short int stream, void * ptr, int count );`
* ## ASM
* `>PUSHB stream`
* `>PUSHW ptr`
* `>PUSHW count`
* `>SYSCALL fread`
* ## RETURN VALUE
*  Y,A = Bytes Read
*\--------------------------------------
K.FRead			jsr PFT.CheckNode4
				bcs K.FWrite.RET5

				jsr UNISTD.Read
				bcs K.FWrite.9

K.FRead.RTS		rts
*/--------------------------------------
* # FWrite (BLOCKING)
* Write bytes to file
* ## C
* `int fwrite ( short int stream, const void * ptr, int count );`
* ## ASM
* `>PUSHB stream`
* `>PUSHW ptr`
* `>PUSHW count`
* `>SYSCALL fwrite`
* ## RETURN VALUE
*  Y,A = Bytes Written
*\--------------------------------------
K.FWrite.PFT	ldx #_FWrite			Needed by PFT

K.FWrite		jsr PFT.CheckNode4
				bcs K.FWrite.RET5

				jsr UNISTD.Write

				bcc K.FRead.RTS

K.FWrite.9		cmp #E.NODATA
				sec
				bne K.FRead.RTS			IO Error

				dec pStack				FF = NODATA
				dec pStack
				dec pStack
				dec pStack
				dec pStack				keep stream, ptr & count on stack
				inc						0 = BLOCKING
*				sec
				rts

K.FWrite.RET5	>RET 5
*/--------------------------------------
* # FFlush
* ## C
* `int fflush( short int stream );`
* ## ASM
* `lda stream`
* `>SYSCALL fflush`
*\--------------------------------------
K.FFlush		jsr PFT.CheckNodeA
				bcs .9

				lda (pFD)
				bne STDIO.IOERR
				>MLICALL MLI.FLUSH

.9				rts
*--------------------------------------
STDIO.IOERR		lda #MLI.E.IO
				sec
				rts
*/-------------------------------------
* # FSeek
* Set the file-position indicator for hFILE
* ## C
* `int fseek( short int stream, long offset, short int whence );`
* ## ASM
* `>PUSHB stream`
* `>PUSHL offset`
* `>PUSHB whence`
* `>SYSCALL fseek`
*\-------------------------------------
K.FSeek			ldy #5
				jsr PFT.CheckNodeY
				bcc .11

				>RET 6

.11				>PULLA					whence
				tax

				>PULLL ACC32			offset

				inc pStack				discard hFile

				lda (pFD)
				bne STDIO.IOERR

				cpx #SEEK.END
				beq .30

				bcs .98

				dex
				beq .20

				stz K.MLI.PARAMS+2
				stz K.MLI.PARAMS+3
				stz K.MLI.PARAMS+4
				bra .8

* SEEK.CUR
.20				>MLICALL MLI.GETMARK
				bcc .8
				rts

* SEEK.END
.30				>MLICALL MLI.GETEOF
				bcs .9

.8				ldy #0

				clc

.81				lda K.MLI.PARAMS+2,y
				adc ACC32,y
				sta K.MLI.PARAMS+2,y

				iny
				tya					3 bytes, 24 bits!!!
				eor #3
				bne .81

				bcs .99					Offset out of range!

.82				>MLICALL MLI.SETMARK
				bcc .9

				cmp #MLI.E.BEYEOF
				bne .9

				>MLICALL MLI.SETEOF
				bcc .82

.9				rts

.98				lda #E.BADARG
				.HS 2C					bit abs
.99				lda #E.FTB
*				sec
K.FSeek.RTS		rts
*/--------------------------------------
* # FEOF
* Test the end-of-file indicator for hFILE
* ## C
* `short int feof( short int stream );`
* ## ASM
* `lda stream`
* `>SYSCALL feof`
* ## RETURN VALUE
*  CC :
*  A = $ff EOF
*  A = 0 NOT EOF
*  CS :
*\--------------------------------------
K.FEOF			jsr PFT.CheckNodeA
				bcs K.FSeek.RTS

				lda (pFD)
				tax
				jmp (.1,x)

.1				.DA FS.EOF.REG
				.DA STDIO.IOERR			DIR
				.DA DEV.EOF
				.DA STDIO.IOERR			BDEV
				.DA STDIO.IOERR			LNK
				.DA STDIO.IOERR			DSOCK
				.DA SOCK.EOF
				.DA PIPE.EOF
*/--------------------------------------
* # FTell
* Return the current value of the file-position indicator
* ## C
* `long ftell( short int stream );`
* ## ASM
* `lda stream`
* `>SYSCALL ftell`
* ## RETURN VALUE
* On stack (long)
*\--------------------------------------
K.FTell			jsr PFT.CheckNodeA
				bcs .9

				>MLICALL MLI.GETMARK
				bcs .9

				lda #0
				>PUSHA

				ldy #2

.1				lda K.MLI.PARAMS+2,y
				>PUSHA
				dey
				bpl .1

.9				rts
*/--------------------------------------
* # Remove
* Remove a file or directory
* ## C
* `int remove ( const char *pathname );`
* ## ASM
* `>LDYA pathname`
* `>SYSCALL remove`
* ## RETURN VALUE
*\--------------------------------------
K.Remove		jsr PFT.CheckPathYA
				bcs .9

				>MLICALL MLI.DESTROY
.9				rts
*/--------------------------------------
* # Rename
* Rename a file
* ## C
* `int rename ( const char * oldpath, const char * newpath );`
* ## ASM
* `>PUSHW oldpath`
* `>PUSHW newpath`
* `>SYSCALL rename`
* ## RETURN VALUE
*\--------------------------------------
K.Rename		jsr PFT.CheckPath2
				bcs .9

				lda (pStack)
				sta ZPPtr1

				ldy #1
				lda (pStack),y
				sta ZPPtr1+1

				dey						ldy #0

.1				lda (ZPPtr1),y
				beq .8

				iny
				sta K.Buf256,y
				cpy #MLI.MAXPATH
				bne .1

.8				sty K.Buf256
				>LDYAI K.Buf256
				>STYA K.MLI.PARAMS+3
				>MLICALL MLI.RENAME

.9				>RET 4
*/--------------------------------------
* # PrintF (BLOCKING)
* # FPrintF (BLOCKING)
* # SPrintF
* Prints C-Style String
* ## C
* `int printf ( const char *format, ... );`
* `int fprintf ( short int stream, const char *format, ... );`
* `int sprintf ( char *str, const char *format, ... );`
* ## ASM
* PrintF : (example is for printing Y,A as integer : format="%I", 2 bytes)
* `>PUSHW format`
* `>PUSHW i`
* `...`
* `>PUSHBI 2`	#bytecount
* `>SYSCALL PrintF`
* FPrintF :
* `>PUSHB hFILE`
* `>PUSHW format`
* `>PUSHW i`
* `...`
* `>PUSHBI 2`	#bytecount
* `>SYSCALL fprintf`
* SPrintF :
* `>PUSHW str`
* `>PUSHW format`
* `>PUSHW i`
* `...`
* `>PUSHBI 2`	#bytecount
* `>SYSCALL sprintf`
* ## RETURN VALUE
* CC : success, Y,A = bytes sent
* CS : error, A = code from Output
* Specifiers :
* + %b : pull 1 byte to Print BIN
* + %d : pull 1 byte unsigned DEC 0..255
* + %D : pull 2 bytes unsigned DEC 0..65535
* + %u : pull 4 bytes long unsigned DEC 0..4294967295
* + %e : pull 5 Bytes float (-)1.23456789e+12
* + %f : pull 5 Bytes float (-)3.1415
* + %h : pull 1 byte to Print HEX
* + %H : pull 2 bytes to Print HEX
* + %i : pull 1 byte to Print signed DEC -128..127
* + %I : pull 2 bytes to Print signed DEC -32768..32767
* + %L : pull 4 bytes signed DEC -2147483648..2147483647
* + %s : pull 2 bytes ptr to C-Style String
* + %S : pull 2 bytes ptr to P-Style String
* Modifiers for len and padding :
* + %d	  : '9'  '12'
* + %2d	  : ' 9' '12'
* + %02d  : '09' '12'
* + %11s  : 'ABCDEFGH   '
* + %011s : 'ABCDEFGH000'
* + %2f	  :	'3.14'
*\--------------------------------------
				.DUMMY					ZPTMP+5,5  Used by : STDIO2
				.OR ZPTMP+5				5 Bytes
PrintF.Cnt		.BS 2
PrintF.hFILE	.BS 1
STDIO.iStkB		.BS 1
STDIO.PopCnt	.BS 1
				.ED
*--------------------------------------
K.PrintF.PadL	.EQ FAC+5
K.PrintF.PadC	.EQ ARG.SIGN
*--------------------------------------
K.PrintF		ldy #S.PS.hStdOut
				lda	(pPS),y
				sta PrintF.hFILE

				ldx #1
				.HS 2C					BIT ABS
*--------------------------------------
K.FPrintf		ldx #2
				.HS 2C					BIT ABS
*--------------------------------------
K.SPrintf		ldx #3
*--------------------------------------
K.PrintF.1		sec						format string->ptr2
				jsr STDIO.GetParams

				stx pIOBuf
				sta pIOBuf+1			Output buffer->pIOBuf

				sty STDIO.PopCnt		Total bytes to POP

.1				jsr SHARED.GetCP2
				beq .8					end of format..

.22				cmp #'%'
				bne .20

				stz K.PrintF.PadL
				stz K.PrintF.PadC
				lda (ZPPtr2)
				beq .7					end of format... print % and exit

				jsr ZP.IsDigit
				bcs .6					no digit....go check specifier

				cmp #'0'				...a 0...mmm... padding char?
				bne .4

				sta K.PrintF.PadC
				jsr SHARED.NextCP2	skip 0 ...
				lda (ZPPtr2)
				beq .7

				jsr ZP.IsDigit
				bcs .6					%0x ??????

.4				jsr MATH.Dec2ACC32
				bcs .99

				lda ACC32
				sta K.PrintF.PadL
				lda K.PrintF.PadC
				bne .5

				lda #C.SPACE
				sta K.PrintF.PadC

.5				jsr SHARED.AddY2P2		skip all processed chars

				lda (ZPPtr2)
				beq .7

.6				ldx	#PrintFTBL1.Cnt-1	do we have a %x command?

.61				cmp PrintFTBL1,x
				beq .62

				dex
				bpl	.61

				bra .20					unknown ...

.62				jsr SHARED.NextCP2
				txa						yes, jmp to it!
				asl
				tax
				jsr PrintF.ESC
				bcc .1

				bra .99

.7				lda #'%'

.20				jsr	PrintF.PutC
				bcc .1
				
				jmp STDIO.Exit
*--------------------------------------
.99				lda #E.BADARG
				sec
				jmp STDIO.Exit
*--------------------------------------
.8				lda PrintF.hFILE
				beq .80					Writing to buffer, append \0

				>PUSHA
				>PUSHWI K.IOBuf
				>PUSHW PrintF.Cnt		Writing to File/dev...
				
				jsr K.FWrite.PFT
				bcc .81

				tay
				bne .9

				>RET 5					0=BLOCKING

.80				ldy PrintF.Cnt			A=0, Writing to buffer, append \0
				sta (pIOBuf),y
				clc

.81				>LDYA PrintF.Cnt
*				clc
.9				jmp STDIO.Exit
*--------------------------------------
PrintFTBL1		.AS	"bdDuefhHiILsS"
PrintFTBL1.Cnt	.EQ *-PrintFTBL1
*--------------------------------------
PrintF.ESC		jmp (.1,x)

.1				.DA PrintF.B
				.DA PrintF.D,PrintF.DD,PrintF.U
				.DA PrintF.E,PrintF.F
				.DA PrintF.H,PrintF.HH
				.DA PrintF.I,PrintF.II,PrintF.L
				.DA PrintF.S,PrintF.SS
*--------------------------------------
PrintF.B		jsr STDIO.GetStkB
				bcs PrintF.B.RTS
				ldy #8

.1				asl
				pha
				lda #'0'/2
				rol
				jsr PrintF.PutC
				bcs .9

				pla
				dey
				bne .1

				rts

.9				ply
PrintF.B.RTS
				rts
*--------------------------------------
PrintF.I		sec						signed short
				.HS 90					BCC
PrintF.D		clc						unsigned short (BYTE)

				ldy #1
				bra PrintF.NUM

PrintF.II		sec						signed int
				.HS 90					BCC
PrintF.DD		clc						unsigned int (WORD)

				ldy #2
				bra PrintF.NUM

PrintF.L		sec						signed long
				.HS 90					BCC
PrintF.U		clc						unsigned long (DWORD)

				ldy #4

PrintF.NUM		sty .2+1

				ror ACC32.Sign			save signed/unsigned flag
				jsr M32.ACC32Z

.1				jsr STDIO.GetStkB
				bcs PrintF.B.RTS

				sta ACC32-1,y			PULL 4,2 or 1
				dey
				bne .1

				bit ACC32.Sign
				bpl .4

.2				ldy #$ff				SELF MODIFIED

				lda ACC32-1,y			Get highest Byte
				bpl .4					positive....

				lda #$ff

.3				cpy #4
				beq .4

				iny
				sta ACC32-1,y
				bra .3

.4				ldx K.PrintF.PadL
				ldy K.PrintF.PadC

				rol ACC32.Sign			get back signed/unsigned flag
				jsr MATH.ACC322STR10
				bra PrintF.StrNum
*--------------------------------------
* EXP(8) 1(s) 1significants(31)
* http://apple2.org.za/gswv/a2zine/GS.WorldView/Resources/GS.TECH.INFO/AppleSoft/
*--------------------------------------
PrintF.E		sec						Force "E+12"
				.HS 90					BCC
PrintF.F		clc

				lda	(pStack)			get current stack Ptr
				sec						at least 5 bytes remaining ?
				sbc #5
				bcc PrintF.StrNum.Err

				sta (pStack)

*				sec
				adc pStack
				ldy pStack+1			A,Y = float
				ldx #FPU.SETFAC
				jsr GP.ROMCALL

				ldy #FOUTBuf+1			FOUT.1 will do a DEY
				ldx #FPU.FOUT
				jsr GP.ROMCALL

PrintF.StrNum	ldy #0
.2				lda FOUTBuf,y
				beq .8

				iny
				jsr PrintF.PutC
				bcc .2

.9				rts

.8				clc
				rts
PrintF.StrNum.Err
				lda #E.STACK
				sec
				rts
*--------------------------------------
PrintF.S		ldy #$ff				CSTR
				.HS 2C					bit abs
PrintF.SS		ldy #$00				PSTR

				sty .1+1

				jsr STDIO.GetStkB
				bcs .9

				sta ZPPtr1+1
				jsr STDIO.GetStkB
				bcs .9

				sta ZPPtr1

				lda (ZPPtr1)			if CSTR:last char=0, if PSTR:len=0
				beq .8

				ldy .1+1

.1				lda #$ff				Self Modified
				bne .11					CSTR

				tya						PSTR
				cmp (ZPPtr1)			len check

				beq .2

.11				iny
				lda	(ZPPtr1),y
				beq .2

				jsr PrintF.PutC
				bcs .9

				lda K.PrintF.PadL
				beq .1

				cpy	K.PrintF.PadL
				bne .1

.8				clc
				rts

.2				lda K.PrintF.PadL
				beq .8

.3				cpy K.PrintF.PadL
				beq .8

				lda K.PrintF.PadC
				jsr PrintF.PutC
				bcs .9

				iny
				bne .3

*				clc
.9				rts
*--------------------------------------
PrintF.HH		jsr STDIO.GetStkB
				bcs STDIO.RTS

				pha						LO byte
				jsr STDIO.GetStkB
				plx
				bcs STDIO.RTS

				pha
				txa
				jsr PrintF.H.1
				plx
				bcs STDIO.RTS

				txa
				bra PrintF.H.1
*--------------------------------------
PrintF.H		jsr STDIO.GetStkB
				bcs STDIO.RTS

PrintF.H.1		jsr STDIO.A2HexAX
				jsr PrintF.PutC
				bcs STDIO.RTS

				txa
*--------------------------------------
PrintF.PutC		phy
				ldy PrintF.Cnt
				sta (pIOBuf),y
				ply
				inc PrintF.Cnt
				bne .8

				lda PrintF.hFILE
				bne .9

				inc pIOBuf+1
				inc PrintF.Cnt+1

.8				clc
				rts

.9				lda #E.BUF
				sec
STDIO.RTS		rts
*/--------------------------------------
* # ScanF (BLOCKING)
* # FScanF (BLOCKING)
* # SScanF
* Read formatted data from string
* ## C
* `int scanf( const char *format, ... );`
* `int fscanf( short int stream, const char *format, ... );`
* `int sscanf ( const char *s, const char *format, ... );`
* ## ASM
* ScanF :
* `>PUSHW format`
* `>PUSHW ptr`
* `...`
* `>PUSHB bytecount`
* `>SYSCALL scanf`
* FScanF :
* `>PUSHB stream`
* `>PUSHW format`
* `>PUSHW ptr`
* `...`
* `>PUSHB bytecount`
* `>SYSCALL fscanf`
* SScanF :
* `>PUSHW s`
* `>PUSHW format`
* `>PUSHW ptr`
* `...`
* `>PUSHB bytecount`
* `>SYSCALL sscanf`
* Specifiers :
* + %i : short int
* + %d : byte
* + %I : int
* + %D : word
* + %L : long int
* + %U : dword
* + %h : HEX byte
* + %H : HEX word
* + %s : string
* TODO : %10s
* ## RETURN VALUE
* A = Number of arguments filled.
*\--------------------------------------
K.ScanF			ldy #S.PS.hStdIn
				lda	(pPS),y
				sta PrintF.hFILE

				ldx #1
				.HS 2C					BIT ABS
*--------------------------------------
K.FScanF		ldx #2
				.HS 2C					BIT ABS
*--------------------------------------
K.SScanF		ldx #3
*--------------------------------------
K.SScanF.1		clc						format string->ptr1
				jsr STDIO.GetParams		stz PrintF.Cnt

				stx ZPPtr2
				sta ZPPtr2+1			Output buffer->ZPPtr2

				sty STDIO.PopCnt		Total bytes to POP

				ldx PrintF.hFILE
				beq .1

				txa
				>PUSHA
				>PUSHW pIOBuf
				>PUSHWI 256
				jsr K.FGetS
				bcc .1

				tax
				bne STDIO.RTS
				>RET 4

.1				jsr SHARED.GetCP1	End Of format?
				beq .8

				cmp #'%' 				Escape ?
				beq .2

				cmp #C.SPACE			Space ?
				beq .12

				sta .11+1

				jsr SHARED.GetCP2
				beq .9

.11				cmp #$ff				Same char in string?
				beq .1

				bra .9

.12				jsr SHARED.GetCP2
				beq .9

				cmp #C.SPACE
				bne .9

.13				jsr SHARED.GetCP2
				cmp #C.SPACE			another space ?
				beq .13

				bra .1

.2				jsr SHARED.GetCP1	Get specifier after %
				beq .9					unexpected End of format after "%" ?

				ldx #K.SScanFJMP-K.SScanFTBL-2

.3				cmp K.SScanFTBL,x
				beq .4
				dex
				dex
				bpl .3

.9				lda #MLI.E.EOF
				sec
				jmp STDIO.Exit

.4				jsr STDIO.GetStkB
				bcs .9

				sta ZPPtr3+1
				jsr STDIO.GetStkB
				bcs .9

				sta ZPPtr3

				jsr .5
				bcs .9					out of Ptr on stack

				inc PrintF.Cnt			parsed one more arg!
				bra .1					no chance more than 256 ptrs on stack

.8				ldy PrintF.Cnt			Arg processed
				lda #0
				clc
				jmp STDIO.Exit
*--------------------------------------
.5				jmp (K.SScanFJMP,x)
*--------------------------------------
K.SScanFTBL		.DA #'i,#1,#'d,#1,#'I,#2,#'D,#2,#'l,#4,#'u,#4,#'h,#1,#'H,#2,#'s,#2
K.SScanFJMP		.DA K.SScanF.I
				.DA K.SScanF.D
				.DA K.SScanF.II
				.DA K.SScanF.DD
				.DA K.SScanF.L
				.DA K.SScanF.U
				.DA K.SScanF.H
				.DA K.SScanF.HH
				.DA K.SScanF.S
*--------------------------------------
K.SScanF.I
K.SScanF.D
K.SScanF.II
K.SScanF.DD
K.SScanF.L
K.SScanF.U		lda K.SScanFTBL+1,x		Get VAR size
				pha						Save VAL size

				jsr MATH.Dec2ACC32
				bra K.SScanF.GetVAL
*--------------------------------------
K.SScanF.HH
K.SScanF.H		lda K.SScanFTBL+1,x		Get VAR size
				pha

				jsr MATH.Hex2ACC32

K.SScanF.GetVAL	jsr SHARED.AddY2P2		Y=char count parsed

				ply						get back VAL size

.1				lda ACC32-1,y
				dey
				sta (ZPPtr3),y
				bne .1

				rts
*--------------------------------------
K.SScanF.S		ldy #$ff

.1				iny
				lda (ZPPtr2),y			Get char in string to scan
				sta (ZPPtr3),y			store in param ptr
				beq K.SScanF.Fwd		end of string to scan ?

				cmp (ZPPtr1)			match format next char ?
				beq .2

				cmp #C.SPACE			is it a space ?
				bne .1

.2				lda #0					add \0 to param ptr
				sta (ZPPtr3),y

K.SScanF.Fwd	jmp SHARED.AddY2P2		Y=char count parsed
*--------------------------------------
* IN:
* CC : format in ZPPtr1
* CS : format in ZPPtr2
* X = 3 : get format & buffer
* X = 2 : get format & hFile
* X = 1 : get format only
* OUT:
* X = Buf LO
* A = Buf HI
* format on stack
* Y = BytePtr
*--------------------------------------
STDIO.GetParams	stz PrintF.Cnt
				stz PrintF.Cnt+1

				lda (pStack)			Bytecount

				tay
				sty STDIO.iStkB

				iny
				lda (pStack),y			format LO
				pha

				iny
				lda (pStack),y			format HI
				bcs .10

				sta ZPPtr1+1
				pla
				sta ZPPtr1
				bra .11

.10				sta ZPPtr2+1
				pla
				sta ZPPtr2

.11				dex
				beq .1

				dex
				beq .2

.3				stz PrintF.hFILE

				iny
				lda (pStack),y			str LO
				tax

				iny
				lda (pStack),y			str HI

				rts

.2				iny
				lda (pStack),y			hFILE
				sta PrintF.hFILE

.1				ldx #K.IOBuf
				lda /K.IOBuf

				rts
*--------------------------------------
STDIO.GetStkB	phy

				ldy STDIO.iStkB
				beq .9

				lda (pStack),y
				dec STDIO.iStkB

				ply
				clc
				rts

.9				lda #E.STACK

				ply
				sec
				rts
*--------------------------------------
STDIO.Exit		php
				pha

				lda pStack
				sec
				adc STDIO.PopCnt
				sta pStack

				pla
				plp
				rts
*--------------------------------------
* Convert A to 2 hex digits in AX
*--------------------------------------
STDIO.A2HexAX	pha

				and #$0F
				jsr .8

				tax

				pla
				lsr
				lsr
				lsr
				lsr

.8				ora #$30
				cmp #'9'+1
				bcc .9

				adc #6

.9				rts
*--------------------------------------
MAN
SAVE usr/src/sys/kernel.s.stdio
LOAD usr/src/sys/kernel.s
ASM
