NEW
  AUTO 3,1
				.LIST OFF	
*--------------------------------------
CORE.Init		>LDYAI 256
				>SYSCALL GetMem
				bcs .9
				>STYA ZPArgVBuf
				txa
				>STA.G CORE.hArgVBuf
				
.9				rts				
*--------------------------------------
CORE.Quit		>LDA.G CORE.hArgVBuf
				beq CORE.FUNCRESET
				>SYSCALL FreeMem

CORE.FUNCRESET	>LDA.G hFuncList
				beq CORE.Quit.9
	
				>SYSCALL SListFree
				>STZ.G hFuncList
	
CORE.Quit.9		rts	
*--------------------------------------
* http://heirloom.sourceforge.net/sh/sh.1.html
*--------------------------------------
* Input : ZPArgVBuf (String)
* Tokenize ZPArgVBuf
* :LOOP
* if CmdSep=| : 
*    set hStdIn = hStdOut
*    set hStdOut = Std
* GetCmd from line until | or EOL
* if CmdSep=| :
*     create PIPE
*     set hStdOut -> PIPE
*	  CORE.Exec &
*      :LOOP
* else CORE.Exec
*--------------------------------------
* SET VAR = `cmd args`, FOR VAR IN `cmd args`
* create PIPE
* set hStdOut -> PIPE
* CORE.Exec `cmd args` &
* set READMODE
* set hStdIn = hStdOut
* set hStdOut = Std
*--------------------------------------
CORE.Run.SYN	lda #E.SYN
				sec
				rts
				
CORE.Run		>LDYA ZPInputBufPtr		Save Actual cmd for looping
				>STYA ZPInputCmdPtr

				>LDYA ZPArgVBuf
				>STYA ZPArgVBufPtr
				
				lda #0					Reset ArgV Buffer
				sta (ZPArgVBuf)
				
				lda #S.PS.F.HOLD
				>STA.G CORE.PSFlags
				
				lda #$ff
				
				>STA.G CORE.IntCmd		assume external
				
				jsr CORE.GetCharNB
				bcc .11
				
				lda #0					EOF
				jsr CMD.EXIT.A
				bcs .9

				jsr IO.Reset
				lda #0
				sec
				rts						Ending 0, CS,A=0
				
.11				cmp #'|'
				bne .21
				
				jsr IO.Pipe.In
				bcs .9
				
				jsr CORE.GetNextCharNB	Skip |
				bcs CORE.Run.SYN

				bra .3
				
.21				pha
				jsr IO.Reset
				pla
				
.3				cmp #C.CR				empty line ?
				bne .33
				
				jsr CORE.GetNextChar	skip CR...
				bra .8
				
.33				cmp #'#'				commented line?
				bne .2

.12				jsr CORE.SkipLine

.8				jsr IO.Reset
				
				lda #0
				clc
.9				rts						EOL, CS,A=0
				
.2				>LDA.G bFuncMode
				bpl .4
				
				jmp CORE.AddFunc

.4				>LDYA L.CMD				internal command ?
				jsr CORE.LookupInputBuf
				bcc .41
				
.40				jsr CORE.ArgV.Add		external cmd, go check context
				bra .42
				
.41				jsr CORE.SkipCharsA
				
				txa
				>STA.G CORE.IntCmd
				
.42				jsr CORE.StkGet			
				bcs CORE.Run.7			no particular context, exec...
				tax
				
				>LDA.G CORE.IntCmd
				bmi .45
				
				and #$3F
				cmp #C.SWITCH			SWITCH....FI ?
				bcs CORE.Run.7

.45				txa
				bpl .43					context is FALSE, skip line	
				
				asl				
				bmi CORE.Run.7			parent context is true, exec
				
.43				jsr CORE.GetCharNB
				
				bcs .44					EOF

				cmp #C.CR
				beq .44
				
				cmp #';'				TODO ";"
				beq .44

				jsr CORE.GetNextChar
				bra .43
				
.44				jsr CORE.GetNextCharNB	Skip EoL char
				clc
.99				rts
*--------------------------------------
CORE.Run.5		>LDYA L.CORE.IO
				jsr CORE.LookupInputBuf
				bcs CORE.Run.6

				jsr CORE.SkipCharsA

				jsr CORE.IO.JMP
				bcs CORE.Run.RTS
				bra CORE.Run.7
				
CORE.Run.6		jsr CORE.ArgV.Add
				
CORE.Run.7		jsr CORE.GetCharNB
				bcs CORE.ExecCmd.1		Nothing to skip
				
				jsr CORE.IsEndCmd
				bcs CORE.Run.5
				
				cmp #'|'
				bne CORE.ExecCmd		skip CR, ;
				
				jsr IO.Pipe.Out
				bcs CORE.Run.RTS

				jsr CORE.IO.AMP			run in background
				
				bra CORE.ExecCmd.1		Do not skip |
						
CORE.Run.RTS	rts				
*--------------------------------------
* Input : ZPArgVBuf
*--------------------------------------
CORE.ExecCmd	jsr CORE.GetNextCharNB	Skip EoL char

CORE.ExecCmd.1	lda #0
				sta (ZPArgVBufPtr)
				
				>LDYA ZPArgVBuf
				>STYA ZPArgVBufPtr

				>LDA.G CORE.IntCmd
				bmi CORE.ExecExtCmd
				asl
				tax
				jmp (J.CMD,x)
				
CORE.ExecExtCmd	>PUSHB.G CORE.PSFlags
				>LDYA ZPArgVBuf
				>SYSCALL execv
				
CORE.ExecExtCmd.Exit				
				bcs .9
				
				tax						CPID
				
				>LDA.G CORE.PSFlags
				and #S.PS.F.HOLD
				bne .4
				
				txa
				>PUSHA
				>PUSHBI 1
				>PUSHW L.MSG.PID
				ldy #S.PS.hStdErr
				lda (pPS),y				
				>SYSCALL fprintf
				rts
				
.4				>SLEEP					Suspend this PID
				
				sec
				ldy #S.PS.RC			CPID will update S.PS.RC
				lda (pPs),y
				bne .9
				
.8				clc
.9				rts
*--------------------------------------
CORE.AddFunc	ldy #$ff

.1				iny
				lda (ZPInputBufPtr),y
				beq .9
				
				cmp #C.SPACE
				beq .1
				
				jsr ToUpperCase
				cmp #'E'
				bne .8
				
				iny
				lda (ZPInputBufPtr),y
				beq .9
				
				jsr ToUpperCase
				cmp #'N'
				bne .8

				iny
				lda (ZPInputBufPtr),y
				beq .9
				
				jsr ToUpperCase
				cmp #'D'
				bne .8
				
				iny
				lda (ZPInputBufPtr),y
				beq .9
				
				cmp #C.SPACE
				beq .7
				cmp #C.CR
				bne .9
				
.7				lda #0
				>STA.G bFuncMode
				
				jsr .8					add "END"
				bcs .9
				
				jmp CMD.END.FUNC		Cleanup Stk

.9				jmp CORE.Run.SYN
				
.8				ldy #0

.80				lda (ZPInputBufPtr),y
				iny
				beq .82
				cmp #C.CR
				bne .80
				
.82				lda #0
				>PUSHYA					DataLen
				>PUSHW ZPInputBufPtr	DataPtr

				lda (pData)
				tay
				dey						skip C.FUNC
				lda (pData),y			KeyID
				>PUSHA
				dey
				lda (pData),y			KeyID
				>PUSHA
				>LDA.G hFuncList
				>SYSCALL SListAddData
				bcs .9
*--------------------------------------
CORE.SkipLine	jsr CORE.GetNextCharNB
				bcs .8					EOF

				cmp #C.CR				EOL
				bne CORE.SkipLine
				
				jsr CORE.GetNextChar	skip CR...

.8				rts
*--------------------------------------
* search ZPInputBufPtr/ZPArgVBufPtr in Y,A table
*--------------------------------------
CORE.LookupInputBuf
				>STYA ZPPtr1
				>LDYA ZPInputBufPtr
				bra CORE.Lookup
CORE.LookupArgVBuf				
				>STYA ZPPtr1
				>LDYA ZPArgVBufPtr
				
CORE.Lookup		>STYA ZPPtr2

				ldx #0
				
.1				ldy #$ff
				
.2				iny
				lda (ZPPtr2),y
				beq .3					Src Keyword end
			
				jsr CORE.IsSpaceOrEndCmd
				bcc .3					Src Keyword end
				
				lda (ZPPtr1),y
				beq .4					Table Keyword end
				lda (ZPPtr2),y

				jsr ToUpperCase
				
				cmp (ZPPtr1),y			
				beq .2

				bra .4
				
.3				lda (ZPPtr1),y
				bne .4
				
				tya						Keyword Len
				dey
				clc			
.8				rts
				
.4				inc ZPPtr1
				bne .5
				inc ZPPtr1+1

.5				lda (ZPPtr1)
				bne .4
				
				inc ZPPtr1
				bne .6
				inc ZPPtr1+1
								
.6				inx
				
				lda (ZPPtr1)			Array Ending 0, must be an external Cmd....
				bne .1
				
				lda #E.SYN
				sec
				rts
*--------------------------------------
* ArgV
*--------------------------------------
CORE.ArgV.Dup	>STYA ZPPtr1
				phy
				pha
				
				lda #1
				sta ZPPtr2
				stz ZPPtr2+1
				
.1				lda (ZPPtr1)
				beq .4
				
				ldy #0

.2				iny
				lda (ZPPtr1),y
				bne .2
				
				jsr CORE.ArgV.DupNextY
				bra .1
				
.4				pla
				ply
				>STYA ZPPtr1
				
				>LDYA ZPPtr2
				>SYSCALL GetMem
				bcs .9
				
				>STYA ZPPtr2

				lda #$ff			Arg count-1 (skip $0)
				pha
				
.5				lda (ZPPtr1)
				sta (ZPPtr2)
				beq .8
				
				pla
				inc
				pha
				
				ldy #0

.6				iny
				lda (ZPPtr1),y
				sta (ZPPtr2),y
				bne .6

				jsr CORE.ArgV.DupNextY
				bra .5
				
.8				pla						Arg count
				clc				
.9				rts				
*--------------------------------------
CORE.ArgV.DupNextY			
				tya
				sec
				adc ZPPtr1
				sta ZPPtr1
				bcc .1
				inc ZPPtr1+1

.1				tya
				sec
				adc ZPPtr2
				sta ZPPtr2
				bcc .8
				inc ZPPtr2+1
.8				rts
*--------------------------------------
CORE.ArgV.Add	>LDYA ZPArgVBufPtr
				>STYA ZPArgVBufPrev		Save String start of Expand

				lda #C.SPACE
				sta M32.TMP
				
				jsr CORE.GetCharNB
				bcs .9

				cmp #'"'
				bne .10
				sta M32.TMP
				bra .1
				
.10				cmp #'('
				bne .11
				ldx #')'
				stx M32.TMP

				bra .12
	
.11				cmp #'`'
				bne .12
				sta M32.TMP
				
.12				jsr CORE.ArgV.PutChar

.1				jsr CORE.GetNextChar
				bcs .5
				
.2				cmp M32.TMP
				bne .3
				jsr CORE.GetNextChar
				bra .5

.3				ldy M32.TMP
				cpy #C.SPACE
				bne .40
				jsr CORE.IsEndCmd
				bcc .5
				
.40				jsr CORE.ArgV.PutChar
				
.4				jsr CORE.GetNextChar
				bcc .2
				
.5				lda #0
				jsr CORE.ArgV.PutChar

				>LDYA ZPArgVBufPrev
				>SYSCALL ExpandStr
				bcs .9
				phx
				>STYA ZPPtr1
	
				>LDYA ZPArgVBufPrev
				>STYA ZPArgVBufPtr

				ldy #$ff

.7				iny
				lda (ZPPtr1),y
				beq .8
				jsr CORE.ArgV.PutChar
				bra .7
				
.8				tya
				beq .81
				
				lda #0
				jsr CORE.ArgV.PutChar
				
.81				pla
				>SYSCALL freemem
.9				rts
*--------------------------------------
CORE.ArgV.PutChar
				sta (ZPArgVBufPtr)
CORE.ArgV.NextChar
				inc ZPArgVBufPtr
				bne .8
				inc ZPArgVBufPtr+1
.8				rts				
*--------------------------------------
CORE.ArgV.Next	lda (ZPArgVBufPtr)
				beq .8
				
				>LDYA ZPArgVBufPtr
				>STYA ZPArgVBufPrev
				
.1				jsr CORE.ArgV.NextChar
				lda (ZPArgVBufPtr)
				bne .1
				
				jsr CORE.ArgV.NextChar
				lda (ZPArgVBufPtr)

.8				rts
*--------------------------------------
* IO
*--------------------------------------
CORE.IO.JMP		txa
				asl
				tax
				jmp (J.CORE.IO,x)

CORE.IO.AMP		>LDA.G CORE.PSFlags
				and #$ff^S.PS.F.HOLD
				sta (pData),y
				clc
CORE.IO.RTS		rts
				
CORE.IO.IN		lda #O.RDONLY+O.TEXT
				jsr CORE.IO.Open
				bcs CORE.IO.RTS
				jmp IO.Set.In
CORE.IO.OUTA
CORE.IO.1OUTA	lda #O.WRONLY+O.APPEND+O.CREATE+O.TEXT
				bra CORE.IO.OUT.1
CORE.IO.OUT		
CORE.IO.1OUT	lda #O.WRONLY+O.TRUNC+O.CREATE+O.TEXT

CORE.IO.OUT.1	jsr CORE.IO.Open
				bcs CORE.IO.RTS
				jmp IO.Set.Out

CORE.IO.2OUTA	lda #O.WRONLY+O.APPEND+O.CREATE+O.TEXT
				bra CORE.IO.2OUT.1
CORE.IO.2OUT	lda #O.WRONLY+O.TRUNC+O.CREATE+O.TEXT

CORE.IO.2OUT.1	jsr CORE.IO.Open
				bcs CORE.IO.RTS
				jmp IO.Set.Err
*--------------------------------------
CORE.IO.Open	pha						Open Mode
				jsr CORE.GetCharNB
				bcs .9					no arg left....

				jsr CORE.ArgV.Add		Get Filename

				>PUSHWI 0				Aux type
				>PUSHBI S.FI.T.TXT		ftype
				pla
				>PUSHA					flags
				>LDYA ZPArgVBufPrev
				>STYA ZPArgVBufPtr		Discard filename
				>SYSCALL fopen
				rts
				
.9				pla
				lda #E.SYN
				sec
				rts				
*--------------------------------------
* Input Buffer
*--------------------------------------
CORE.IsSpaceOrEndCmd
				cmp #C.SPACE
				beq CORE.IsEndCmd.8
				
CORE.IsEndCmd	cmp #';'
				beq CORE.IsEndCmd.8
				cmp #C.CR
				beq CORE.IsEndCmd.8
				cmp #'|'
				beq CORE.IsEndCmd.8
				sec
				rts
				
CORE.IsEndCmd.8	clc
				rts
*--------------------------------------
CORE.GetCharNB	jsr CORE.GetChar
				bcs CORE.GetNextCharNB.RTS
				jsr CORE.CheckCharNB
				bcc CORE.GetNextCharNB.RTS		
*--------------------------------------
CORE.GetNextCharNB
				jsr CORE.GetNextChar
				bcs CORE.GetNextCharNB.RTS
				jsr CORE.CheckCharNB
				bcs CORE.GetNextCharNB
CORE.GetNextCharNB.RTS
				rts
*--------------------------------------
CORE.CheckCharNB
				cmp #C.SPACE
				beq .9
				cmp #C.LF
				beq .9
				cmp #C.TAB
				beq .9
				clc
.9				rts				
*--------------------------------------
CORE.GetNextChar
				inc ZPInputBufPtr
				bne CORE.GetChar
				inc ZPInputBufPtr+1
*--------------------------------------
CORE.GetChar	lda (ZPInputBufPtr)
				beq .9
				clc
				rts
				
.9				sec
				rts
*--------------------------------------
CORE.SkipCharsA	clc
				adc ZPInputBufPtr
				sta ZPInputBufPtr
				bcc .8
				inc ZPInputBufPtr+1
.8				rts				
*--------------------------------------
* Stack
*--------------------------------------
CORE.StkCheck	sec
				adc (pData)				StackPtr
				cmp #CORE.STACK.MAX
				lda #E.STKOVERFLOW
				rts				
*--------------------------------------
CORE.StkPushPtr	bcs .1
				lda ZPInputCmdPtr
				ldx ZPInputCmdPtr+1
				bra .2
				
.1				lda ZPInputBufPtr
				ldx ZPInputBufPtr+1
				
.2				jsr CORE.StkPush
				bcs CORE.StkPullPtr.9
				txa
				bra CORE.StkPush
*--------------------------------------
CORE.StkPushYA	phy
				jsr CORE.StkPush
				pla
*--------------------------------------
CORE.StkPush	pha
				lda (pData)				StackPtr
				inc
				cmp #CORE.STACK.MAX
				beq .9
				sta (pData)				StackPtr
				tay
				pla	
				sta (pData),y
*				clc
				rts
				
.9				pla
				lda #E.STKOVERFLOW
*				sec
				rts
*--------------------------------------
CORE.StkGetPtr	lda (pData)				StackPtr
				beq CORE.StkErr
				dec
				beq CORE.StkErr
				
				tay

				lda (pData),y
				sta ZPInputBufPtr
				iny
				lda (pData),y
				sta ZPInputBufPtr+1
				
				clc
				rts
				
CORE.StkErr		lda #E.STACKERROR
				sec
				rts
*--------------------------------------
CORE.StkGetCtx	jsr CORE.StkGet
				tax
				bcs .1					no context...
				cmp #$C0				in a call...
				beq .1					CS

				and #$80				get current..
				lsr						becomes parent
				bra .2
				
.1				lda #$40				...set Parent = true

.2				>STA.G CORE.Test

				txa
				rts
*--------------------------------------
CORE.StkPullPtr	jsr CORE.StkPull
				bcs CORE.StkPullPtr.9
				sta ZPInputBufPtr+1
				jsr CORE.StkPull
				bcs CORE.StkPullPtr.9
				sta ZPInputBufPtr
CORE.StkPullPtr.9		
				rts				
*--------------------------------------
CORE.StkPull	jsr CORE.StkGet
				bcs .9
				
				dey
				pha
				tya
				sta (pData)				StackPtr
				pla
				
.9				rts				
*--------------------------------------
CORE.StkGet		lda (pData)				StackPtr
				beq CORE.StkErr
				tay
				lda (pData),y
				clc
				rts
*--------------------------------------
MAN
SAVE USR/SRC/BIN/SH.S.CORE
LOAD USR/SRC/BIN/SH.S
ASM
