NEW
  AUTO 3,1
*/--------------------------------------
* # StrToF
* Convert String to 40 bits Float
* ## C
* `float strtof (const char* str, char** endptr );`
* ## ASM
* `>PUSHW str`
* `>PUSHWI EndPtr`
* `>SYSCALL StrToF`
* ## RETURN VALUE
* On stack (float)
*\--------------------------------------
K.StrToF		>PULLW ZPPtr1
				>PULLYA
				jsr K.AToF

				lda TXTPTR
				sta (ZPPtr1)
				ldy #1
				lda TXTPTR+1
				sta (ZPPtr1),y
				rts
*/--------------------------------------
* # AToF
* Convert String to 40 bits Float
* ## C
* `float atof ( const char* str );`
* ## ASM
* `>LDYA str`
* `>SYSCALL atof`
* ## RETURN VALUE
* On stack (float)
*\--------------------------------------
K.AToF			>STYA TXTPTR			Ptr to source string
				lda pStack
				sec
				sbc #5
				sta pStack
				jsr CHARGOT

				ldx #FPU.FIN
				jmp GP.GetFac
*/--------------------------------------
* # StrToL/StrToUL
* Convert String to 32 bits (unsigned) int
* ## C
* `long strtol (const char* str, char** endptr, int base);`
* `unsigned long strtoul (const char* str, char** endptr, int base);`
* ## ASM
* `>PUSHW str`
* `>PUSHW EndPtr`
* `>PUSHB Base`
* `>SYSCALL StrToL`
* ## RETURN VALUE
* On stack (long)
*\--------------------------------------
K.StrToL		sec						Signed
				.HS 90					BCC
K.StrToUL		clc						Unsigned

				>PULLA					Base
				>PULLW ZPPtr1			EndPtr
				>PULLW ZPPtr2			str

				jsr K.AToL.I
				bcs K.StrToUL.rts
*				clc

				adc ZPPtr2
				sta (ZPPtr1)
				lda #0
				adc ZPPtr2+1
				ldy #1
				sta (ZPPtr1),y
K.StrToUL.rts	rts
*/--------------------------------------
* # atol
* Convert String to 32 bits long
* ## C
* `long atol ( const char * str );`
* ## ASM
* `>LDYA str`
* `>SYSCALL atol`
* ## RETURN VALUE
* On stack (long)
*\--------------------------------------
K.AToL			>STYA ZPPtr2			C-String in Ptr2, Dst buffer in Ptr1

*				lda #10					base 10
				sec						signed
K.AToL.I		jsr MATH.Dec2ACC32
				bcs .9
				ldx #3

.3				lda ACC32,x
				>PUSHA
				dex
				bpl .3

				tya						Y = A = Count processed
*				clc
.9
				rts
*/--------------------------------------
* # atoi
* Convert String to 16 bits int
* ## C
* `int atoi ( const char * str );`
* ## ASM
* `>LDYAI str`
* `>SYSCALL atoi`
* ## RETURN VALUE
*  Y,A = int
*\--------------------------------------
K.atoi			>STYA ZPPtr2
*				lda #10					base 10
				sec						signed
				jsr MATH.Dec2ACC32
				bcs .9
				>LDYA ACC32

.9				rts
*/--------------------------------------
* # RealPath
* Return the canonicalized absolute pathname
* ## C / CSH
* `char *realpath(const char *path, char *resolvedpath);`
* ## ASM
* `>PUSHW path`
* `>PUSHW resolvedpath`
* `>SYSCALL realpath`
* ## RETURN VALUE
* CC : success
*  Y,A = Ptr to Full Path (C-String Buffer, MLI.MAXPATH+1)
*  X = hMem of Full Path
* CS : A = Error Code
*\--------------------------------------
K.realpath.DST	.BS 2

K.realpath.RET4	>RET 4

K.realpath		ldy #3
				lda (pStack),y
				>PUSHA
				lda (pStack),y
				>PUSHA
				>PUSHWZ
				jsr K.expand
				bcs K.realpath.RET4

				>STYA ZPPtr1
				stx .99+1				save expanded buffer hMem

				>PULLW K.realpath.DST	resolved path

				inc pStack				discard path
				inc pStack

				ldx #$ff

				lda (ZPPtr1)

				cmp #'/'				full path starting with '/'?
				beq .3					yes, do not append to current prefix

.1				ldy #S.PS.hCWD
				lda (pPS),y
				jsr K.GetMemPtr
				>STYA .20+1

				ldy #$ff

.2				iny
				inx
.20				lda $ffff,y
				sta K.Buf256,x
				bne .2

				dex

.3				ldy #$ff

.4				iny
				inx
				lda (ZPPtr1),y
				sta K.Buf256,x
				bne .4

				dex
				beq .81					we have '/'....nothing to do...
*--------------------------------------
* X=LEN, K.Buf256 = /dir1/./../file(/)\0
*--------------------------------------
				ldx #0					will skip leading /

.5				ldy #0					reset dot counter=0

.6				inx
				lda K.Buf256,x
				beq .8

.7				cmp #'/'
				beq .8

				cmp #'.'
				bne .5

				iny
				bra .6

.8				tya
				beq .80					Y was 0....nothing to do...

				dey						one dot ?
				bne .9					no..

				dex
				dex
				jsr K.RealPath.RemoveAtX	we found "/.", remove,useless....
				bra .80

.9				dey						"/.." ?
				bne .99					"/..." ??!!...syntax error

				dex
				dex
				dex
				txa						we found "/.."
				beq .99					at the beginning of string...cannot remove /dir/..

				jsr K.RealPath.RemoveAtX	remove "/.."

.10				dex
				lda K.Buf256,x			go to "/dir"
				cmp #'/'
				bne .10

				jsr K.RealPath.RemoveAtX ...remove "/dir"

.80				lda K.Buf256,x			was / or \0 ?
				bne .5
*--------------------------------------
.81				jsr .99

.82				ldy K.realpath.DST
				lda K.realpath.DST+1
				bne .85

				>LDYAI MLI.MAXPATH+1
				jsr K.getmem
				bcs .90

.85				>STYA ZPPtr1

				ldy #$ff

.83				iny
				lda K.Buf256,y
				sta (ZPPtr1),y
				bne .83

				>LDYA ZPPtr1

				clc
				rts

.99				lda #$ff				SELF MODIFIED
				jsr K.FreeMem

				lda #E.BADPATH
				sec
.90				rts
*--------------------------------------
K.RealPath.RemoveAtX
				txa						X = "/something"
				tay
.1				iny
				lda K.Buf256,y
				beq .2					found /something\0

				cmp #'/'
				bne .1					found /something/

.2				phx						save X for exit

.3				iny						K.Buf256,y=/ or 0
				inx
				lda K.Buf256-1,y
				sta K.Buf256-1,x
				bne .3

				txa
				bne .8

				lda #'/'				Make sure we have a least '/' in the buffer
				sta K.Buf256
				stz K.Buf256+1

.8				plx						restore X
				rts
*/--------------------------------------
* # Expand
* ## C
* `char *expand(const char *str, char *expanded);`
* ## ASM
* `>PUSHW str`
* `>PUSHW expanded`
* `>SYSCALL expand`
* ## RETURN VALUE
* if expanded == null
*  Y,A = PTR to Expanded String
*  X = hMem to Expanded String
* if expanded != null
*  Y,A = strlen
*\--------------------------------------
K.Expand		ldy #2
				lda (pStack),y
				pha
				iny
				lda (pStack),y
				ply

				jsr K.strdup
				bcc .1

				jmp .9

.1				phx						Save temp string...
				>STYA TXTPTR

				stz	ENV.BufPtr			init Expanded String len=0
				stz ENV.bExp			No var found yet
				stz ENV.bNoExp			Reset no expand flag

.10				lda (TXTPTR)			End of CSTR?
				beq .80

				jsr SHARED.TXTPTRn

.11				cmp #'''
				bne .21

				lda ENV.bNoExp
				eor #$ff
				sta ENV.bNoExp			toggle flag
				bra	.10

.21				bit ENV.bNoExp
				bpl .23

.22				jsr ENV.AddAToBuf
				bra .10

.23				cmp #'$'				no, found one ?
				bne .22					no, store...

				lda (TXTPTR)
				bne .24

				lda #'$'				End of string, output $
				bra .22

.24
*				sec
				ror ENV.bExp			Toggle Expanded flag
				stz ENV.VarEndChar
				cmp #'{'				 "${VAR]"?
				bne .31

				dec ENV.VarEndChar		"}" expected

				jsr SHARED.TXTPTRn	skip "{"
				bra .40

.31				jsr ENV.SysVar			0-9 *#?@$!
				bcs .40

.35				jsr SHARED.TXTPTRn	skip $x
				bra .10

.40				jsr ENV.ExpandStrVar
				bcc .70

.50				ldy ENV.BufPtr
				lda /K.Buf256
				>STYA FORPNT

				ldx #_GetEnv
				jsr K.GetEnv.I
				bcs .70

				ldx ENV.BufPtr

.51				lda K.Buf256,x
				beq .52
				inx
				bra .51

.52				stx	ENV.BufPtr

.70				lda (TXTPTR)
				beq .72

				jsr SHARED.IsIDValid
				bcs .72
				jsr SHARED.TXTPTRn
				bra .70

.72				lda ENV.VarEndChar
				bne .35					skip "}" and loop

				bra .10

.80				ldx ENV.BufPtr
				stz K.Buf256,x

				pla						discard temp string
				jsr K.FreeMem

				bit ENV.bExp			Did we expand something ?
				bpl .81

				jsr STRING.DupBuf256
				bcs .9

				jmp .1

.81				ldy #1
				lda (pStack),y
				beq .83

				sta ZPPtr1+1
				lda (pStack)
				sta ZPPtr1

				ldy #$ff

.82				iny
				lda K.Buf256,y
				sta (ZPPtr1),y
				bne .82

*				Y = len, A = 0

				bra .9

.83				jsr STRING.DupBuf256

.9				>RET 4
*--------------------------------------
ENV.SysVar		jsr ZP.IsDigit			$0 ... $9 ?
				bcs .1

				and #$0f

				jsr K.ArgV
				bcs .8					Arg# is undefined, do not append anything

				jsr ENV.AddYAToBuf

.8				clc
				rts

.1				ldx #ENV.SysVars.Cnt-1

.2				cmp ENV.SysVars,x
				beq .3
				dex
				bpl .2

				sec
				rts

.3				txa
				beq ENV.SysVarsAllArgs

				ldy ENV.SysVars.PS-1,x
				lda (pPS),y
*--------------------------------------
ENV.SysVarsNum	jsr MATH.A2STR10NP

				ldy #0

.1				lda FOUTBuf,y
				beq ENV.SysVarsNum.8

				iny
				jsr ENV.AddAToBuf
				bra .1

ENV.SysVarsNum.8
				clc
				rts
*--------------------------------------
ENV.SysVarsAllArgs
				lda #1
				jsr K.ArgV
				bcs ENV.SysVarsNum.8
				>STYA ZPPtr3

.1				lda (ZPPtr3)
				beq ENV.SysVarsNum.8

.2				jsr ENV.AddP3ToBuf
				jsr ENV.NextEnvP3
				lda (ZPPtr3)
				beq ENV.SysVarsNum.8
				lda #C.SPACE
				jsr ENV.AddAToBuf
				bra .2
*--------------------------------------
ENV.SysVars		.AS "*#?@$!"
ENV.SysVars.Cnt	.EQ *-ENV.SysVars
ENV.SysVars.PS	.DA #S.PS.ARGC,#S.PS.RC,#S.PS.PPID,#S.PS.PID,#S.PS.CPID
*--------------------------------------
ENV.ExpandStrVar
				>LDYAI ENV.StrVars
				>STYA ZPPtr3
				ldx #0

.1				lda (ZPPtr3)
				beq .9

				ldy #$ff
.2				iny
				lda (TXTPTR),y
				beq .3

				jsr SHARED.IsIDValid
				bcs .3

				cmp (ZPPtr3),y
				beq .2

				bra .4

.3				lda (ZPPtr3),y
				bne .4

				jmp (ENV.StrVarsJmp,x)

.4				inx
				inx
				jsr ENV.NextEnvP3
				bra .1

.9				sec
				rts
*--------------------------------------
ENV.StrVars		.AZ "PWD"
				.DA #0
*--------------------------------------
ENV.StrVarsJmp	.DA ENV.StrVarsPWD
*--------------------------------------
ENV.StrVarsPWD	ldy #S.PS.hCWD
				lda (pPS),y
				jsr K.GetMemPtr
*--------------------------------------
ENV.AddYAToBuf	>STYA ZPPtr3
*--------------------------------------
ENV.AddP3ToBuf	ldx ENV.BufPtr
				ldy #$ff

				dex

.1				iny
				inx
				lda (ZPPtr3),y
				sta K.Buf256,x
				bne .1

				stx ENV.BufPtr
				rts
*--------------------------------------
ENV.AddAToBuf	ldx ENV.BufPtr
				sta K.Buf256,x
				inc ENV.BufPtr
				rts
*--------------------------------------
ENV.NextEnvP3	jsr ENV.GetP3LenY

				tya
				sec
				adc ZPPtr3
				sta ZPPtr3
				bcc .8
				inc ZPPtr3+1
.8				rts
*--------------------------------------
ENV.GetP3LenY	ldy #$ff
.1				iny
				lda (ZPPtr3),y
				bne .1
				rts
*--------------------------------------
MAN
SAVE usr/src/sys/kernel.s.stdlib
LOAD usr/src/sys/kernel.s
ASM
