A2osX/SYS/KERNEL.S.STDIO.txt
2023-11-04 15:42:28 +01:00

1438 lines
26 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 #SYS.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 #SYS.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