NEW
  AUTO 3,1
				.LIST OFF
				.OP	65C02
				.OR	$2000
				.TF bin/sh
*--------------------------------------
HIS.MAX			.EQ 10
HISTORY.MAX		.EQ 256
CORE.STACK.MAX	.EQ 128
PUSHD.STACK.MAX	.EQ 4
*--------------------------------------
C...			.EQ 0
C..				.EQ 2
C.CD			.EQ 4
C.NOHUP			.EQ 6
C.DATE			.EQ 8
C.ECHO			.EQ 10
C.EXIT			.EQ 12
C.MD			.EQ 14
C.PAUSE			.EQ 16
C.PWD			.EQ 18
C.RD			.EQ 20
C.READ			.EQ 22
C.REN			.EQ 24
C.SET			.EQ 26
C.SLEEP			.EQ 28
C.SHIFT			.EQ 30
C.PUSHD			.EQ 32
C.POPD			.EQ 34
C.FUNCTION		.EQ 36
C.CALL			.EQ 38
C.BREAK			.EQ 40
C.SWITCH		.EQ 42
C.CASE			.EQ 44
C.DEFAULT		.EQ 46
*--------------------------------------
C.FOR			.EQ 48
C.FOR.LIST			.EQ 0
C.FOR.FILEEXEC		.EQ 1
C.WHILE			.EQ 50
C.IF			.EQ 52
C.NEXT			.EQ 54
C.LOOP			.EQ 56
C.ELSE			.EQ 58
C.FI			.EQ 60
C.END			.EQ 62
*--------------------------------------
C.CLEXEC		.EQ 63
*--------------------------------------
				.INB inc/macros.i
				.INB inc/a2osx.i
				.INB inc/mli.i
				.INB inc/mli.e.i
*--------------------------------------
				.DUMMY
				.OR ZPBIN
ZS.START
ZPCLBuf			.BS 2
ZPInputBuf		.BS 2
ZPInputBufPtr	.BS 2
ZPInputCmdPtr	.BS 2

ZPArgVBuf		.BS 2
ZPArgVBufPrev	.BS 2
ZPArgVBufPtr	.BS 2
ZPVarNamePtr	.BS 2

CORE.PSFlags	.BS 1
CORE.IntCmd		.BS 1
CORE.Operator	.BS 1
CORE.LogicOp	.BS 1
CORE.TestResult	.BS 1
CORE.PrevTestResult	.BS 1
ZPTmpW			.BS 2

ZPPtr1			.BS 2
ZPPtr2			.BS 2

M32.ACC			.BS 4

ZS.END			.ED
*--------------------------------------
*			File Header (16 Bytes)
*--------------------------------------
CS.START		cld
				jmp (.1,x)
				.DA #$61				6502,Level 1 (65c02)
				.DA #1					BIN Layout Version 1
				.DA #S.PS.F.EVENT		S.PS.F
				.DA #0
				.DA CS.END-CS.START		Code Size (without Constants)
				.DA DS.END-DS.START		Data SegmentSize
				.DA #64					Stack Size
				.DA #ZS.END-ZS.START	Zero Page Size
				.DA 0
*--------------------------------------
* Relocation Table
*--------------------------------------
.1				.DA CS.INIT
				.DA CS.RUN
				.DA CS.DOEVENT
				.DA	CS.QUIT
*--------------------------------------
L.MSG.GREETINGS	.DA MSG.GREETINGS
L.MSG.HIS		.DA MSG.HIS
L.MSG.HISPROMPT	.DA MSG.HISPROMPT
L.MSG.HISROMPTCLR	.DA MSG.HISROMPTCLR
L.MSG.PROMPT	.DA MSG.PROMPT
L.MSG.PROMPTCRLF	.DA MSG.PROMPTCRLF
L.MSG.TRACE		.DA MSG.TRACE
L.MSG.ECHOCRLF	.DA MSG.ECHOCRLF
L.MSG.BATCHLINE	.DA MSG.BATCHLINE
L.MSG.BATCHERR	.DA MSG.BATCHERR
L.MSG.ERROR		.DA MSG.ERROR
L.MSG.PID		.DA MSG.PID
L.FMT.DATE		.DA FMT.DATE
L.FMT.Long		.DA FMT.Long
L.FMT.Byte		.DA FMT.Byte
J.ESC			.DA CL.BS			left arrow
				.DA HIS.GetNext			
				.DA HIS.GetPrev
				.DA CL.NAK			right arrow
L.CD..			.DA CD..
L.IN			.DA IN
L.CMD			.DA CMD
J.CMD			.DA CMD...
				.DA CMD..
				.DA CMD.CD
				.DA CMD.NOHUP
				.DA CMD.DATE
				.DA CMD.ECHO
				.DA CMD.EXIT
				.DA CMD.MD
				.DA CMD.PAUSE
				.DA CMD.PWD
				.DA CMD.RD
				.DA CMD.READ
				.DA CMD.REN
				.DA CMD.SET
				.DA CMD.SLEEP
				.DA CMD.SHIFT
				.DA CMD.PUSHD
				.DA CMD.POPD
				.DA CMD.FUNCTION
				.DA CMD.CALL
				.DA CMD.BREAK
				.DA CMD.SWITCH
				.DA CMD.CASE
				.DA CMD.DEFAULT
				.DA CMD.FOR
				.DA CMD.WHILE
				.DA CMD.IF
				.DA CMD.NEXT
				.DA CMD.LOOP
				.DA CMD.ELSE
				.DA CMD.FI
				.DA CMD.END
L.CORE.IO		.DA CORE.IO
J.CORE.IO		.DA CORE.IO.AMP
				.DA CORE.IO.IN
				.DA CORE.IO.OUTA
				.DA CORE.IO.OUT
				.DA CORE.IO.1OUTA
				.DA CORE.IO.1OUT
				.DA CORE.IO.2OUTA
				.DA CORE.IO.2OUT
L.EXP.BEGIN		.DA EXP.BEGIN
L.EXP.OP.UNARY	.DA EXP.OP.UNARY
J.EXP.OP.UNARY	.DA EXP.OP.UNARY.D
				.DA EXP.OP.UNARY.E
				.DA EXP.OP.UNARY.F
				.DA EXP.OP.UNARY.I
				.DA EXP.OP.UNARY.N
				.DA EXP.OP.UNARY.X
				.DA EXP.OP.UNARY.Z
L.EXP.OP.BINARY	.DA EXP.OP.BINARY
L.EXP.OP.MATH	.DA EXP.OP.MATH
L.EXP.OP.LOGIC	.DA EXP.OP.LOGIC
L.HOME.PROFILE	.DA HOME.PROFILE
L.PtrZero		.DA PtrZero
L.HOME			.DA HOME
L.PS1			.DA PS1
				.DA 0
*--------------------------------------
CS.INIT			clc
				rts
*--------------------------------------
CS.RUN			jsr CL.Init
				jsr CORE.Init

				ldy #S.PS.ARGC
				lda (pPS),y
				beq .2					no arg, continue starting interactive

				lda #$ff
				>STA.G bExitOnEOF
				inc						lda #0
				jsr CMD.SHIFTA			Remove $0 = /bin/sh

				jsr GetArgV
				>STYA ZPPtr1

				lda (ZPPtr1)
				cmp #'-'
				bne .1

				ldy #1
				lda (ZPPtr1),y
				cmp #'c'
				beq .10
				
				cmp #'C'
				bne .1
				
.10				iny
				lda (ZPPtr1),y
				bne .1
				
*				lda #0				
				jsr CMD.SHIFTA			Remove $0 = -C
				
				jsr GetArgV
				jmp CS.RUN.CMDLINE
				
.1				jsr GetArgV				Load SH batch file
				>SYSCALL LoadTxtFile
				bcs .9

				phx						X = loaded file hMem
				jsr GetArgV				Y,A = Args
				plx
				jsr CMD..EXEC.YAX		Execute . Batch file
				bcc CS.RUN.LOOP
				
.9				rts
*--------------------------------------
.2				jsr CMD.CD.HOME
				jsr HIS.Init
				bcs .9

				>PUSHW L.MSG.GREETINGS
				>PUSHW A2osX.KVER
				>PUSHBI 2
				>SYSCALL PrintF
				bcs .9

				>LDYA L.HOME.PROFILE
				>SYSCALL LoadTxtFile
				bcs CS.RUN.LOOP			No profile...

				>LDYA L.HOME.PROFILE
				jsr CMD..EXEC.YAX		Execute . ${home}profile
*--------------------------------------
CS.RUN.LOOP		>SLEEP

.1				jsr CheckSleep
				beq .2

				ldy #S.PS.hStdIn
				lda (pPS),y
				>SYSCALL FEOF
				bcs .9

				tay
				bne CS.RUN.LOOP

				>SYSCALL GetChar
				bcs .9					I/O err

				cmp #3					Ctrl-C
				bne .11

				lda (pData)				batch mode ?
				beq CS.RUN.LOOP

				>LDA.G bSET.C
				beq .8

				bra CS.RUN.LOOP

.11				cmp #19					test Ctrl-s
				bne CS.RUN.LOOP

				lda #$80
				>STA.G bPause
				bra CS.RUN.LOOP
*--------------------------------------
.8				lda #3					User Interrupt
				sec
.9				rts
*--------------------------------------
.2				>LDA.G bPause
				bpl .6

.3				>SYSCALL GetChar
				bcs	.9					I/O err

				cmp #3					Ctrl-C
				bne .4

				lda (pData)				batch mode ?
				beq .5

				>LDA.G bSET.C
				beq .8

				bra .5

.4				tax
				>LDA.G bPause
				asl						$ff ?
				bpl .5					not from PAUSE command

				cpx #C.CR
				bne .5
				jsr CheckLFAfterCR		Check for any extra LF
				bcs .9 
				
.5				>STZ.G bPause
*--------------------------------------
.6				lda (pData)				batch mode ?
				bne CS.RUN.BATCH
*--------------------------------------
CS.RUN.INTERACTIVE
				jsr IO.Reset
				jsr CL.Reset

				jsr CL.ReadResetV

				jsr CL.PrintPrompt
				bcs CS.RUN.CMDLINE.9

.1				>SYSCALL GetChar
				bcs CS.RUN.CMDLINE.9	I/O error 

.2				cmp #C.EOF				....or Ctrl-D
				beq CS.RUN.CMDLINE.9	CS

				jsr CL.CHARIN

				>LDA.G CL.bReady		Something to execute ?
				bpl .1

				>PUSHW L.MSG.PROMPTCRLF
				>PUSHBI 0
				>SYSCALL PrintF
				bcs CS.RUN.CMDLINE.9

				lda (ZPCLBuf)
				beq CS.RUN.LOOP.END		Empty line

				jsr HIS.Add

				>LDYA ZPCLBuf

CS.RUN.CMDLINE	>SYSCALL StrDup
				bcs CS.RUN.CMDLINE.9
				
				phx
				jsr GetArgV
				plx						Y,A=ARGV, X=strdup

				jsr CORE.Load.YAX		Exec CL
				bcs CS.RUN.CMDLINE.9

				lda #$C0+C.CLEXEC
				jsr CORE.StkPush

				bra CS.RUN.LOOP.RUN

CS.RUN.CMDLINE.9
				rts			
*--------------------------------------
CS.RUN.BATCH	>LDA.G bSET.X
				beq CS.RUN.LOOP.RUN

				ldy #$ff

.3				iny
				lda (ZPInputBufPtr),y
				sta (ZPCLBuf),y
				beq .4

				eor #C.CR
				bne .3

				sta (ZPCLBuf),y

.4				>PUSHW L.MSG.TRACE
				>PUSHW ZPCLBuf
				>PUSHBI 2
				>SYSCALL PrintF
				bcs CS.RUN.LOOP.RTS

CS.RUN.LOOP.RUN	jsr CORE.Run

CS.RUN.LOOP.END	ldy #S.PS.RC
				sta (pPS),y
				bcc CS.RUN.LOOP.80
				tay
				beq CS.RUN.LOOP.80		0 = EOF

				>LDA.G bSET.E
				bmi CS.RUN.LOOP.80

.1				jsr CORE.StkGet
				cmp #$C0+C.CLEXEC
				beq .8

				cmp #$C0+C..			in . ?
				beq .7

				cmp #$C0+C.CALL			in CALL ?
				beq .7
				
				jsr CORE.StkPopCtx
				bcc .1

.7				jsr IO.PrintBatchErrMsg
				bcs CS.RUN.LOOP.RTS
				
				jsr CORE.StkPull
				jsr CMD.EXIT.FILE

.8				jsr IO.PrintErrMsg
				bcs CS.RUN.LOOP.RTS

CS.RUN.LOOP.80	lda (pData)				something on stack ?
				bne CS.RUN.LOOP.88

				>LDA.G bExitOnEOF
				bmi CS.RUN.LOOP.EXIT

CS.RUN.LOOP.88	jmp CS.RUN.LOOP
CS.RUN.LOOP.EXIT
				ldy #S.PS.RC
				lda (pPS),y
				sec
CS.RUN.LOOP.RTS	rts
*--------------------------------------
CS.DOEVENT		lda (pEvent)
				bpl .9

				jsr CheckSleep
				beq .9

*				ldy #Sleep				already set by CheckSleep
				ldx #4
				clc
.1				lda (pData),y
				sbc #0
				sta (pData),y
				iny
				dex
				bne .1

.9				sec
				rts
*--------------------------------------
CS.QUIT			jsr CORE.FUNCRESET

				>LDA.G HIS.hBuf
				beq .1
	
				>SYSCALL FreeStkObj

.1				ldy #CL.hBuf
				jsr .7

.2				jsr CMD.POPD
				bcc .2

				ldy #CORE.hArgVBuf

.7				lda (pData),y
				beq .8
				
				>SYSCALL FreeMem
				
.8				clc
				rts
*--------------------------------------
GetCWD			ldy #S.PS.hCWD
				bra GetArgV.1
*--------------------------------------
GetArgV			ldy #S.PS.hARGV

GetArgV.1		lda (pPS),y
				>SYSCALL GetMemPtr
				rts
*--------------------------------------
CheckLFAfterCR	ldy #S.PS.hStdIn		Check for any extra LF
				lda (pPS),y
				>SYSCALL FEOF
				bcs .9
				
				tay
				bne .9
				>SYSCALL GetChar
				
.9				rts
*--------------------------------------
CheckSleep		ldy #Sleep+3
				lda (pData),y
				dey
				ora (pData),y
				dey
				ora (pData),y
				dey
				ora (pData),y
				rts
*--------------------------------------
GetPtr1NextChar	lda (ZPPtr1)
				beq IncPtr1.8

IncPtr1			inc ZPPtr1
				bne IncPtr1.8
				inc ZPPtr1+1
IncPtr1.8		rts
*--------------------------------------
GetPtr1LenY		ldy #$ff
.1				iny
				lda (ZPPtr1),y
				bne .1
				rts
*--------------------------------------
GetPtr1NextString
				jsr GetPtr1LenY
*--------------------------------------
				tya
AddAp1Ptr1		sec

				adc ZPPtr1
				sta ZPPtr1
				bcc .8
				inc ZPPtr1+1
.8				rts
*--------------------------------------
ToUpperCase		cmp #'a'
				bcc .8
				cmp #'z'+1
				bcs .8
				eor #$20
.8				clc						exit CC to allow Jmp to
				rts
*--------------------------------------
IncPStack4		inc pStack
IncPStack3		inc pStack
				inc pStack
				inc pStack
				rts
*--------------------------------------
				.INB usr/src/bin/sh.s.cl
				.INB usr/src/bin/sh.s.his
				.INB usr/src/bin/sh.s.core
				.INB usr/src/bin/sh.s.io
				.INB usr/src/bin/sh.s.cmd
				.INB usr/src/bin/sh.s.exp
*--------------------------------------
CS.END
*--------------------------------------
MSG.GREETINGS	.AZ "\r\nA2osX-SH %d.%d\r\n\r\n"
MSG.HIS			.AZ "\r\n%3d : %s"
MSG.HISPROMPT	.AZ "\r\n\r\n? "
MSG.HISROMPTCLR .DA #C.BS,#C.BS,#0
MSG.PROMPT		.AZ "\e[?7h$ "			Enable Line Wrap
MSG.PROMPTCRLF	.AZ "\e[?7l\r\n"		Disable Line Wrap
MSG.TRACE		.AS ">"
MSG.BATCHLINE	.AZ "%s\r\n"
MSG.BATCHERR	.AZ "%s^\r\nLine #%D:"
MSG.ERROR		.AS "[$%h]:%s."
MSG.ECHOCRLF	.AZ "\r\n"
MSG.PID			.AZ "PID=%d\r\n"
FMT.DATE		.AZ "%A, %B %d %Y %H:%M:%S"
FMT.Long		.AZ "%L"
FMT.Byte		.AZ "%d"
*--------------------------------------
HOME.PROFILE	.AZ "${HOME}profile"
PtrZero			.HS 00					To Make It ArgV
PS1				.AZ "${PS1}"
HOME			.AZ "${HOME}"
*--------------------------------------
EscChars		.AS 'DBAC'
EscChars.Cnt	.EQ *-EscChars
EscChars.Remap	.DA #C.BS,#C.VT,#C.LF,#C.FS
*--------------------------------------
DEV				.AS "/dev/"
*--------------------------------------
CD..			.AZ ".."
*--------------------------------------
IN				.AZ "IN"
*--------------------------------------
CMD				.AT ".."
				.AT "."
				.AT "CD"
				.AT "NOHUP"
				.AT "DATE"
				.AT "ECHO"
				.AT "EXIT"
				.AT "MD"
				.AT "PAUSE"
				.AT "PWD"
				.AT "RD"
				.AT "READ"
				.AT "REN"
				.AT "SET"
				.AT "SLEEP"
				.AT "SHIFT"
				.AT "PUSHD"
				.AT "POPD"
				.AT "FUNCTION"
				.AT "CALL"
				.AT "BREAK"
				.AT "SWITCH"
				.AT "CASE"
				.AT "DEFAULT"
				.AT "FOR"
				.AT "WHILE"
				.AT "IF"
				.AT "NEXT"
				.AT "LOOP"
				.AT "ELSE"
				.AT "FI"
				.AT "END"
				.HS 00
CORE.IO			.AT "&"
				.AT "<"
				.AT ">>"
				.AT ">"
				.AT "1>>"
				.AT "1>"
				.AT "2>>"
				.AT "2>"
				.HS 00
EXP.BEGIN		.AT "!["
				.AT "["
				.HS 00
EXP.OP.UNARY	.AT "-D"
				.AT "-E"
				.AT "-F"
				.AT "-I"
				.AT "-N"
				.AT "-X"
				.AT "-Z"
				.HS 00
EXP.OP.BINARY	.AT "-LT"
				.AT "-LE"
				.AT "-GT"
				.AT "-GE"
				.AT "-EQ"
				.AT "-NE"
				.AT ".<"
				.AT "<="
				.AT ".>"
				.AT ">="
				.AT "="
				.AT "!="
				.HS 00
EXP.OP.MATH		.AT "*"
				.AT "/"
				.AT "MOD"
				.AT "+"
				.AT "-"
				.HS 00
EXP.OP.LOGIC	.AT "AND"
				.AT "OR"
				.HS 00
*--------------------------------------
EXP.OP.BINARY.BITS
				.DA #%100
				.DA #%110
				.DA #%001
				.DA #%011
				.DA #%010
				.DA #%101
*--------------------------------------
EXP.OP.MATH.FPU	.DA #FPU.lMUL,#FPU.lDIV,#FPU.lMOD,#FPU.lADD,#FPU.lSUB
*--------------------------------------
SET.FLAGS		.AS "CXE"
SET.VARS		.DA #bSET.C,#bSET.X,#bSET.E
*--------------------------------------
				.DUMMY
				.OR 0
DS.START
CORE.STACK		.BS CORE.STACK.MAX+1	pData (0 = Stack Ptr)
PUSHD.STACK		.BS PUSHD.STACK.MAX+1

hFuncList		.BS 1

bExitOnEOF		.BS 1

bPause			.BS 1

bSET.C			.BS 1
bSET.E			.BS 1
bSET.X			.BS 1

Sleep			.BS 4

CL.hBuf			.BS 1

CL.Ptr			.BS 1
CL.Len			.BS 1
CL.bReady		.BS 1
CL.bEscMode		.BS 1
CL.MaxCnt		.BS 1
CL.bSilent		.BS 1

CORE.hArgVBuf	.BS 1
CORE.bPipeIn	.BS 1
CORE.bPipeOut	.BS 1

HIS.hBuf		.BS 1
HIS.Count		.BS 1
HIS.Index		.BS 1
HIS.LRU			.BS 1

IO.hIn			.BS 1
IO.hOut			.BS 1
IO.hErr			.BS 1

*TimeBuf		.BS S.TIME				8 bytes
*M32.BUF		.BS 12					-1234567890\0
TimeBuf			.EQ *
M32.BUF			.EQ *
IO.DEVFIFO		.BS 12					/dev/fifoXX\0
*--------------------------------------
DS.END			.ED
*--------------------------------------
MAN
SAVE usr/src/bin/sh.s
ASM
