NEW
  AUTO 3,1
*--------------------------------------
CORE.Init		lda #PUSHD.STACK
				tay
				sta (pdata),y

				lda #CODE.STACK
				tay
				sta (pdata),y

.9				rts
*--------------------------------------
CORE.FUNCRESET	>LDA.G hFunctions
				beq .8

				>SYSCALL SListFree
				>STZ.G hFunctions

.8				rts
*--------------------------------------
* stack-6,7		old InputBuf
* stack-4,5		old InputBufPtr
* stack-3		old ARGC
* stack-2       old ARGV
* stack-1		new hCode
* stack
*--------------------------------------
CORE.Load.YAX	stx LOAD.hCode			X = Code to Execute

				>SYSCALL ArgVDup		Y,A = ArgV
				bcs .9

				stx LOAD.hArgs			X = hARGV
				sta LOAD.ArgCnt			A = ARGC

				lda #8
				jsr STK.Check
				bcs .9

				>LDYA ZPInputBuf
				jsr STK.PushYA

				jsr STK.PushInputBufPtr

				ldy #S.PS.ARGC
				lda (pPS),y
				jsr STK.Push			old ARGC

				ldy #S.PS.hARGV
				lda (pPS),y
				jsr STK.Push			old hARGV

				ldy #S.PS.ARGC
				lda LOAD.ArgCnt			new ARGC
				dec 					Skip ARG0 in count
				sta (pPS),y

				iny 					#S.PS.hARGV
				lda LOAD.hArgs
				sta (pPS),y				new hARGV

				lda LOAD.hCode			new code
				jsr STK.Push
*				lda LOAD.hCode
				>SYSCALL GetMemPtr
				>STYA ZPInputBuf
				>STYA ZPInputBufPtr

*				clc
.9				rts
*--------------------------------------
* http://heirloom.sourceforge.net/sh/sh.1.html
*--------------------------------------
* CORE.Run
* Input : ZPInputBufPtr (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.EOF	jsr STK.Pull
				bcs *
				cmp #$C0+C..			check CALL . CL context
				beq .1

				cmp #$C0+C.CALL
				beq .1

				cmp #$C0+C.CLEXEC
				bne .9

.1				jsr CMD.EXIT.FILE

				jsr IO.Reset

				lda #0
				sec
				jmp CORE.Run.Exit		Ending 0, CS,A=0

.9				lda #E.UNEXPEOF
				sec
				jmp CORE.Run.Exit

CORE.Run.RTS	rts
*--------------------------------------
CORE.Run	 	>LDYAI 256
				>SYSCALL GetMem
				bcs CORE.Run.RTS

				>STYA ZPArgVBuf
				txa
				>STA.G CORE.hArgVBuf

				lda #bState.PipeIn+bState.PipeOut
				trb bState
*--------------------------------------
CORE.Run.1		>LDYA ZPInputBufPtr		Save Actual ptr for looping
				>STYA ZPInputCmdPtr

				>LDYA ZPArgVBuf			Reset ArgV Buffer
				>STYA ZPArgVBufPtr

				lda #0
				sta (ZPArgVBuf)

				sec
				ror CORE.IntCmd			assume external

				lda #S.PS.F.HOLD
				sta CORE.PSFlags

				jsr CORE.GetCharNB
				bcs CORE.Run.EOF

				cmp #C.CR				empty line ?
				bne .33

				jsr CORE.GetNextChar	skip CR...
				bra .8

.33				cmp #'#'				commented line?
				bne CORE.Run.3

.12				jsr CORE.SkipLine

.8				jmp CORE.Run.Exit0		EOL, CS,A=0
*--------------------------------------
CORE.Run.3		>LDA.G hAliases
				beq CORE.Run.4

				>PUSHA
				>PUSHW ZPInputBufPtr
				>PUSHWZ					ScopeID
				>SYSCALL SListLookup
				bcs CORE.Run.4

				>STYA ZPTmpW			Save KeyID
				txa
				jsr CORE.SkipCharsA

				ldy #hAliases
				jsr CORE.SListGetData
				bcs .9

				jsr CORE.PushBufX
				bcc CORE.Run.3

.9				rts
*--------------------------------------
CORE.Run.4		>LDYA L.CMD				internal command ?
				jsr CORE.LookupInputBuf
				bcc .41

.40				jsr CORE.ArgV.Add		external cmd, go check context
				bra .42

.41				stx CORE.IntCmd
				jsr CORE.SkipCharsA

.42				jsr STK.Get
				bcs CORE.Run.5			no particular context, exec...

				tax
				lda CORE.IntCmd
				bmi .45

				and #$3F
				cmp #C.SWITCH			SWITCH....FI ?
				bcs CORE.Run.5

.45				txa
				bpl .43					context is FALSE, skip line

				asl
				bmi CORE.Run.5			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
				jmp CORE.Run.Exit0
*--------------------------------------
CORE.Run.5		jsr CORE.GetCharNB
				bcs CORE.Run.6			Nothing to skip

				jsr CORE.IsEndCmd
				bcc .3

				>LDYA L.CORE.IO
				jsr CORE.LookupInputBuf
				bcs .2

				jsr CORE.SkipCharsA

				jsr CORE.IO.JMP
				bcc CORE.Run.5

				bcs .9

.2				jsr CORE.ArgV.Add
				bcc CORE.Run.5

.9				lda #E.SYN
				sec
				jmp CORE.Run.Exit
*--------------------------------------
.3				cmp #C.CR
				beq .7

				cmp #';'
				beq .7

				cmp #'|'
				bne .5

				jsr CORE.GetNextCharNB	'|'

				lda #bState.PipeOut
				tsb bState
				bra CORE.Run.6

.5				cmp #'&'
				bne .9

				jsr CORE.GetNextChar	Skip '&'
				bcs .50

				cmp #'&'
				beq .6					&&

.50				lda #S.PS.F.HOLD		Run in the background...
				trb CORE.PSFlags
				bra CORE.Run.6

.6				jsr CORE.GetNextChar	Skip '&&'

				jsr CORE.ExecCmd
				bcc .60

				jsr CORE.SkipLine
				jmp CORE.Run.Exit0

.60				jmp CORE.Run.1

.7				jsr CORE.GetNextCharNB	Skip EoL char
*--------------------------------------
CORE.Run.6		lda bState
				bit #bState.PipeOut
				beq .1

				jsr IO.Pipe.Out
				bcs CORE.Run.Exit
				
				lda #S.PS.F.HOLD		Run in the background...
				trb CORE.PSFlags

				lda #S.PS.F.CLOSEONX	...and child PS must close StdOut on exit
				tsb CORE.PSFlags

.1				jsr CORE.ExecCmd
				bcs CORE.Run.Exit

				lda bState

				bit #bState.PipeIn
				beq .2

				jsr IO.Pop.In			restore Input piping app must close it
				
				lda #bState.PipeIn
				trb bState

				lda bState

.2				bit #bState.PipeOut
				beq CORE.Run.Exit0

				jsr IO.Pipe.In			Set previous Pipe Out to StdIn for next CMD
				bcs CORE.Run.Exit

				lda #bState.PipeIn
				tsb bState

				bit CORE.IntCmd
				bmi .3
				
				jsr IO.Reset.Out		Internal : CLOSE output
				bra .4
				
.3				jsr IO.Pop.Out			External : DONT Close Output, child process will close it

.4				lda #bState.PipeOut
				trb bState
				
.7				jmp CORE.Run.1			Loop with Pipe IN

CORE.Run.Exit0	lda #0
				clc

CORE.Run.Exit	php
				pha
				>LDA.G CORE.hArgVBuf
				beq .1

				>SYSCALL FreeMem

				>STZ.G CORE.hArgVBuf

.1				jsr IO.Reset

				pla
				plp
				rts
*--------------------------------------
* Input : ZPArgVBuf
*--------------------------------------
CORE.ExecCmd	lda #0
				sta (ZPArgVBufPtr)
				>LDYA ZPArgVBuf
				>STYA ZPArgVBufPtr

				lda CORE.IntCmd
				bmi CORE.ExecExtCmd

				asl
				tax
				jmp (J.CMD,x)
*--------------------------------------
CORE.ExecExtCmd	>PUSHW ZPArgVBuf
				>PUSHB CORE.PSFlags

				>SYSCALL ExecV
				bcs .9

				tax						CPID
				lda CORE.PSFlags
				and #S.PS.F.HOLD
				bne .1

				lda bState
				bit #bState.PipeOut
				bne .1

				ldy #S.PS.hStdErr
				lda (pPS),y
				>PUSHA
				>PUSHW L.MSG.PID

				txa
				>PUSHA
				>PUSHBI 1
				>SYSCALL FPrintF
				rts

.1				>SLEEP					Suspend this PID

				ldy #S.PS.RC			CPID will update S.PS.RC
				lda (pPS),y
				cmp #1

.9				rts
*--------------------------------------
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
				sec
				.HS 90					BCC
CORE.LookupArgVBuf
				clc
				>STYA ZPPtr1			Keywords table
				>LDYA ZPArgVBufPtr
				bcc CORE.Lookup

				>LDYA ZPInputBufPtr

CORE.Lookup		>STYA ZPPtr2

				ldx #0

.1				ldy #$ff

.2				jsr .7					get next valid char in src text
				bcs .3

.20				jsr ToUpperCase
				eor (ZPPtr1),y			match table char ?
				asl						compare only 7 bits
				bne .4					no match...get next table keyword

				bcc .2					not last char in this keyword

				jsr .7					next char in text...
				bcc .4					valid....failed

.8				tya						Keyword Len

				clc
				rts

.3				dey
				lda (ZPPtr1),y			was last char in this keyword ?
				bmi .8

				iny
.41				jsr IncPtr1				skip chars to next keyword

.4				lda (ZPPtr1)
				bpl .41

				jsr IncPtr1

.6				inx
				lda (ZPPtr1)			Array Ending 0, lookup failed
				bne .1

				lda #E.SYN

.9				sec
				rts

.7				iny
				lda (ZPPtr2),y			Get Src text char...
				beq .9					end of text

				jsr CORE.IsSpaceOrEndCmd
				bcc .9					end of valid chars
				clc
CORE.ArgV.Add.RTS
				rts
*--------------------------------------
* ArgV
*--------------------------------------
CORE.ArgV.Add	lda #C.SPACE
				sta ZPTmpW

				ldy #0

				jsr CORE.GetCharNB
				bcs CORE.ArgV.Add.RTS

				cmp #'"'
				bne .10

				sta ZPTmpW
				bra .1

.10				cmp #'('
				bne .11

				ldx #')'
				stx ZPTmpW
				bra .12

.11				cmp #'`'
				bne .12

				sta ZPTmpW

.12				sta (ZPArgVBufPtr),y
				iny

.1				jsr CORE.GetNextChar
				bcs .7

.2				cmp ZPTmpW
				bne .3

				jsr CORE.GetNextChar
				bra .7

.3				ldx ZPTmpW
				cpx #C.SPACE
				bne .6

				jsr CORE.IsEndCmd
				bcc .7

.6				sta (ZPArgVBufPtr),y
				iny

				jsr CORE.GetNextChar
				bcc .2

.7				lda #0
				sta (ZPArgVBufPtr),y

				>LDYA ZPArgVBufPtr
				>STYA ZPArgVBufPrev
				>PUSHYA
				>PUSHW ZPArgVBufPtr
				>SYSCALL Expand
				bcs .9

				tya
				beq .8					Empty string....

				sec
				adc ZPArgVBufPtr
				sta ZPArgVBufPtr
				bcc .8

				inc ZPArgVBufPtr+1
				clc

.8
.9				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
*--------------------------------------
CORE.ArgV.NextChar
				inc ZPArgVBufPtr
				bne .8

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

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

				>LDYA ZPArgVBufPrev
				>STYA ZPArgVBufPtr		Discard filename
				plx
				jmp IO.FOpenYAX

.9				pla
				lda #E.SYN
				sec
CORE.IO.RTS		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

				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	clc
				lda (ZPInputBufPtr)
				bne .8

				jsr CORE.PopBuf
				bcc CORE.GetChar

				lda #0

.8				rts
*--------------------------------------
CORE.SkipCharsA	clc
				adc ZPInputBufPtr
				sta ZPInputBufPtr
				bcc .8

				inc ZPInputBufPtr+1

.8				rts
*--------------------------------------
CORE.PushBufX	>LDA.G CODE.STACK
				cmp #CODE.STACK.MAX*5
				beq .9

				inc
				tay

				phx						next hBuffer

				ldx #0

.1				lda ZPInputBuf,x		ZPInputBuf
				sta (pData),y
				inx						ZPInputBufPtr
				iny
				cpx #6					ZPInputCmdPtr
				bne .1

				pla
				pha
				sta (pData),y

				tya
				>STA.G CODE.STACK

				pla
				>SYSCALL GetMemPtr
				>STYA ZPInputBuf
				>STYA ZPInputBufPtr

*				clc
				rts

.9				lda #E.STKOVERFLOW
*				sec
				rts
*--------------------------------------
CORE.PopBuf		phy

				>LDA.G CODE.STACK
				cmp #CODE.STACK
				beq .9

				tay
				lda (pData),y
				phy
				>SYSCALL FreeMem
				ply

				ldx #5
				dey

.1				lda (pData),y			ZPInputBuf
				sta ZPInputBuf,x
				dey                     ZPInputBufPtr
				dex
				bpl .1                  ZPInputCmdPtr

				tya
				>STA.G CODE.STACK

				ply

*				clc
				rts

.9				ply

				lda #E.STACKERROR
*				sec
				rts
*--------------------------------------
CORE.SListGetData
				>PUSHB (pData),y
				>PUSHW ZPTmpW			KeyID
				>PUSHWZ					Allocate
				>PUSHWI $ffff			All
				>PUSHWZ					from Start
				>SYSCALL SListGetData	X = hMem
				rts
*--------------------------------------
MAN
SAVE usr/src/bin/sh.s.core
LOAD usr/src/bin/sh.s
ASM
