mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-12-22 14:30:29 +00:00
1167 lines
25 KiB
NASM
1167 lines
25 KiB
NASM
|
***********************************************************************
|
||
|
*
|
||
|
* The GNO Shell Project
|
||
|
*
|
||
|
* Developed by:
|
||
|
* Jawaid Bazyar
|
||
|
* Tim Meekins
|
||
|
*
|
||
|
**************************************************************************
|
||
|
*
|
||
|
* CMD.ASM
|
||
|
* By Tim Meekins
|
||
|
*
|
||
|
* Command line parsing routines.
|
||
|
*
|
||
|
**************************************************************************
|
||
|
|
||
|
mcopy m/cmd.mac
|
||
|
keep o/cmd.mac
|
||
|
|
||
|
SIGINT gequ 2
|
||
|
SIGSTOP gequ 17
|
||
|
;
|
||
|
; TOKENS used by the parser
|
||
|
;
|
||
|
T_WORD gequ 1
|
||
|
T_BAR gequ 2
|
||
|
T_AMP gequ 3
|
||
|
T_SEMI gequ 4
|
||
|
T_GT gequ 5
|
||
|
T_GTGT gequ 6
|
||
|
T_GTAMP gequ 7
|
||
|
T_GTGTAMP gequ 8
|
||
|
T_LT gequ 9
|
||
|
T_NL gequ 10
|
||
|
T_EOF gequ 11
|
||
|
T_ERROR gequ 12
|
||
|
T_NULL gequ 13
|
||
|
|
||
|
MAXARG gequ 256
|
||
|
BADFD gequ -2
|
||
|
|
||
|
**************************************************************************
|
||
|
*
|
||
|
* Read a token from the buffer.
|
||
|
*
|
||
|
* Input: word points to a buffer to place a word is parsed.
|
||
|
*
|
||
|
* Ouput: the token is placed in the accumulator
|
||
|
*
|
||
|
**************************************************************************
|
||
|
|
||
|
gettoken START
|
||
|
|
||
|
buf equ 1
|
||
|
state equ buf+4
|
||
|
ch equ state+2
|
||
|
space equ ch+2
|
||
|
stream equ space+3
|
||
|
word equ stream+4
|
||
|
end equ word+4
|
||
|
|
||
|
; subroutine (4:word,4:stream),space
|
||
|
|
||
|
tsc
|
||
|
sec
|
||
|
sbc #space-1
|
||
|
tcs
|
||
|
phd
|
||
|
tcd
|
||
|
;
|
||
|
; What state are we in
|
||
|
;
|
||
|
NEUTRAL equ 0 ;a neutral state, get anything
|
||
|
GTGT equ 1 ;looking for a second '>'
|
||
|
INQUOTE equ 2 ;parsing a quoted string
|
||
|
INWORD equ 3 ;parsing a word
|
||
|
SINGQUOTE equ 4 ;single quote string
|
||
|
;
|
||
|
; start in the neutral state
|
||
|
;
|
||
|
ld2 NEUTRAL,state
|
||
|
lda [stream]
|
||
|
sta buf
|
||
|
ldy #2
|
||
|
lda [stream],y
|
||
|
sta buf+2
|
||
|
;
|
||
|
; the main loop
|
||
|
;
|
||
|
loop lda [buf]
|
||
|
inc buf
|
||
|
and2 @a,#$FF,ch
|
||
|
bne switch
|
||
|
|
||
|
if2 state,ne,#INWORD,loop2
|
||
|
jmp endword
|
||
|
|
||
|
loop2 if2 @a,ne,#GTGT,loop3
|
||
|
dec buf
|
||
|
lda #T_GT
|
||
|
jmp done
|
||
|
|
||
|
loop3 if2 @a,eq,#INQUOTE,error1
|
||
|
if2 @a,eq,#SINGQUOTE,error2
|
||
|
lda #T_EOF
|
||
|
jmp done
|
||
|
|
||
|
error1 ldx #^errstr1
|
||
|
lda #errstr1
|
||
|
bra error0
|
||
|
error2 ldx #^errstr2
|
||
|
lda #errstr2
|
||
|
error0 jsr errputs
|
||
|
lda #T_ERROR
|
||
|
jmp done
|
||
|
;
|
||
|
; jump to the current state
|
||
|
;
|
||
|
switch lda state
|
||
|
asl a
|
||
|
tax
|
||
|
jmp (statetbl,x)
|
||
|
statetbl dc a2'case_neutral'
|
||
|
dc a2'case_gtgt'
|
||
|
dc a2'case_inquote'
|
||
|
dc a2'case_inword'
|
||
|
dc a2'case_single'
|
||
|
;
|
||
|
; CASE NEUTRAL
|
||
|
;
|
||
|
case_neutral if2 ch,ne,#';',neut1
|
||
|
lda #T_SEMI
|
||
|
jmp done
|
||
|
neut1 if2 @a,ne,#'&',neut2
|
||
|
lda #T_AMP
|
||
|
jmp done
|
||
|
neut2 if2 @a,ne,#'|',neut3
|
||
|
lda #T_BAR
|
||
|
jmp done
|
||
|
neut3 if2 @a,ne,#'<',neut4
|
||
|
lda #T_LT
|
||
|
jmp done
|
||
|
neut5 cmp #' ' ;space
|
||
|
jeq loop
|
||
|
cmp #9 ;tab
|
||
|
jeq loop
|
||
|
if2 @a,ne,#'>',neut6
|
||
|
lda #GTGT
|
||
|
bra neut10
|
||
|
neut4 if2 @a,ne,#13,neut4a ;return
|
||
|
lda #T_NL
|
||
|
jmp done
|
||
|
neut4a if2 @a,ne,#0,neut4b ;EOF
|
||
|
lda #T_EOF
|
||
|
jmp done
|
||
|
neut4b if2 @a,ne,#'#',neut5 ;comment
|
||
|
neut4c lda [buf]
|
||
|
and #$7F
|
||
|
beq neut4d
|
||
|
inc buf
|
||
|
if2 @a,eq,#13,neut4d
|
||
|
if2 @a,eq,#10,neut4d
|
||
|
bra neut4c
|
||
|
neut4d jmp loop
|
||
|
neut6 if2 @a,ne,#'"',neut7
|
||
|
startquote lda #INQUOTE
|
||
|
bra neut10
|
||
|
neut7 if2 @a,ne,#"'",neut8
|
||
|
startsingle lda #SINGQUOTE
|
||
|
bra neut10
|
||
|
neut8 if2 @a,ne,#'\',neut9
|
||
|
lda [buf]
|
||
|
and #$FF
|
||
|
inc buf
|
||
|
if2 @a,eq,#13,neut10a
|
||
|
neut9 sta [word] ;default
|
||
|
inc word
|
||
|
lda #INWORD
|
||
|
neut10 sta state
|
||
|
neut10a jmp loop
|
||
|
;
|
||
|
; CASE GTGT
|
||
|
;
|
||
|
case_gtgt if2 ch,eq,#'>',gtgt2
|
||
|
if2 @a,eq,#'&',gtgt1
|
||
|
dec buf
|
||
|
lda #T_GT
|
||
|
jmp done
|
||
|
gtgt1 lda #T_GTAMP
|
||
|
jmp done
|
||
|
gtgt2 lda [buf]
|
||
|
and #$FF
|
||
|
if2 @a,eq,#'&',gtgt3
|
||
|
lda #T_GTGT
|
||
|
jmp done
|
||
|
gtgt3 inc buf
|
||
|
lda #T_GTGTAMP
|
||
|
jmp done
|
||
|
;
|
||
|
; CASE INQUOTE
|
||
|
;
|
||
|
case_inquote if2 ch,ne,#'\',quote2 ;is it a quoted character?
|
||
|
lda [buf]
|
||
|
inc buf
|
||
|
putword sta [word]
|
||
|
inc word
|
||
|
jmp loop
|
||
|
quote2 if2 @a,ne,#'"',putword
|
||
|
ld2 INWORD,state
|
||
|
jmp loop
|
||
|
|
||
|
;
|
||
|
; CASE SINGLEQUOTE
|
||
|
;
|
||
|
case_single anop
|
||
|
if2 ch,ne,#"'",putword
|
||
|
ld2 INWORD,state
|
||
|
jmp loop
|
||
|
;
|
||
|
; CASE INWORD
|
||
|
;
|
||
|
case_inword if2 ch,eq,#000,endword
|
||
|
if2 @a,eq,#';',endword
|
||
|
if2 @a,eq,#'&',endword
|
||
|
if2 @a,eq,#'|',endword
|
||
|
if2 @a,eq,#'>',endword
|
||
|
if2 @a,eq,#'<',endword
|
||
|
if2 @a,eq,#' ',endword
|
||
|
if2 @a,eq,#009,endword
|
||
|
if2 @a,eq,#013,endword
|
||
|
cmp #'"'
|
||
|
jeq startquote
|
||
|
cmp #"'"
|
||
|
jeq startsingle
|
||
|
if2 @a,ne,#'\',putword
|
||
|
lda [buf]
|
||
|
inc buf
|
||
|
and #$FF
|
||
|
if2 @a,eq,#13,word2
|
||
|
bra putword
|
||
|
word2 jmp loop
|
||
|
endword dec buf
|
||
|
finiword lda #0
|
||
|
sta [word]
|
||
|
lda #T_WORD
|
||
|
|
||
|
done tax
|
||
|
lda buf
|
||
|
sta [stream]
|
||
|
lda buf+2
|
||
|
ldy #2
|
||
|
sta [stream],y
|
||
|
|
||
|
lda space
|
||
|
sta end-3
|
||
|
lda space+1
|
||
|
sta end-2
|
||
|
pld
|
||
|
tsc
|
||
|
clc
|
||
|
adc #end-4
|
||
|
tcs
|
||
|
|
||
|
txa
|
||
|
rtl
|
||
|
|
||
|
errstr1 dc c'gsh: Missing ending ".',h'0d00'
|
||
|
errstr2 dc c"gsh: Missing ending '.",h'0d00'
|
||
|
|
||
|
END
|
||
|
|
||
|
**************************************************************************
|
||
|
*
|
||
|
* Parse a single command
|
||
|
*
|
||
|
**************************************************************************
|
||
|
|
||
|
command START
|
||
|
|
||
|
pipefds equ 1
|
||
|
errappend equ pipefds+2
|
||
|
errfile equ errappend+2
|
||
|
srcfile equ errfile+4
|
||
|
dstfile equ srcfile+4
|
||
|
count equ dstfile+4
|
||
|
argv equ count+2
|
||
|
word equ argv+4
|
||
|
cmdline equ word+4
|
||
|
pid equ cmdline+4
|
||
|
append equ pid+2
|
||
|
temp equ append+2
|
||
|
argc equ temp+4
|
||
|
token equ argc+2
|
||
|
space equ token+2
|
||
|
stream equ space+3
|
||
|
pipesem equ stream+4
|
||
|
inpipe2 equ pipesem+4
|
||
|
jobflag equ inpipe2+2
|
||
|
inpipe equ jobflag+2
|
||
|
waitpid equ inpipe+2
|
||
|
end equ waitpid+4
|
||
|
|
||
|
; subroutine (4:waitpid,2:inpipe,2:jobflag,2:inpipe2,4:pipesem,4:stream),space
|
||
|
|
||
|
tsc
|
||
|
sec
|
||
|
sbc #space-1
|
||
|
tcs
|
||
|
phd
|
||
|
tcd
|
||
|
|
||
|
ph4 #1024
|
||
|
jsl ~NEW
|
||
|
sta cmdline
|
||
|
stx cmdline+2
|
||
|
lda #0
|
||
|
sta [cmdline]
|
||
|
|
||
|
jsl alloc1024
|
||
|
sta word
|
||
|
stx word+2
|
||
|
|
||
|
ph4 #MAXARG*4
|
||
|
jsl ~NEW
|
||
|
sta argv
|
||
|
stx argv+2
|
||
|
|
||
|
stz srcfile
|
||
|
stz srcfile+2
|
||
|
stz dstfile
|
||
|
stz dstfile+2
|
||
|
stz errfile
|
||
|
stz errfile+2
|
||
|
stz argc
|
||
|
stz pipefds
|
||
|
stz pipefds+2
|
||
|
lda #-3
|
||
|
sta [waitpid]
|
||
|
|
||
|
loop pei (word+2)
|
||
|
pei (word)
|
||
|
pei (stream+2)
|
||
|
pei (stream)
|
||
|
jsl gettoken
|
||
|
sta token
|
||
|
asl a
|
||
|
tax
|
||
|
jmp (toktbl,x)
|
||
|
toktbl dc a2'loop'
|
||
|
dc a2'tok_word'
|
||
|
dc a2'tok_bar'
|
||
|
dc a2'tok_amp'
|
||
|
dc a2'tok_semi'
|
||
|
dc a2'tok_gt'
|
||
|
dc a2'tok_gtgt'
|
||
|
dc a2'tok_gtamp'
|
||
|
dc a2'tok_gtgtamp'
|
||
|
dc a2'tok_lt'
|
||
|
dc a2'tok_nl'
|
||
|
dc a2'tok_eof'
|
||
|
dc a2'tok_error'
|
||
|
;
|
||
|
; Parse a word token
|
||
|
;
|
||
|
tok_word if2 argc,ne,#MAXARG,word1
|
||
|
lda #err00 ;Too many arguments
|
||
|
jmp error
|
||
|
word1 pei (word+2)
|
||
|
pei (word)
|
||
|
jsr cstrlen
|
||
|
inc a
|
||
|
pea 0
|
||
|
pha
|
||
|
jsl ~NEW
|
||
|
sta temp
|
||
|
stx temp+2
|
||
|
ora temp+2
|
||
|
bne word2
|
||
|
lda #err01 ;Out of memory for arguments
|
||
|
jmp error
|
||
|
word2 lda argc ;Copy word to argv[argc]
|
||
|
asl2 a
|
||
|
tay
|
||
|
lda temp
|
||
|
sta [argv],y
|
||
|
lda temp+2
|
||
|
iny2
|
||
|
sta [argv],y
|
||
|
pei (word+2)
|
||
|
pei (word)
|
||
|
pei (temp+2)
|
||
|
pei (temp)
|
||
|
jsr copycstr
|
||
|
|
||
|
stz count ;count illegal characters in word
|
||
|
ldy #0
|
||
|
illword lda [word],y
|
||
|
and #$FF
|
||
|
beq appword
|
||
|
if2 @a,eq,#' ',incword
|
||
|
if2 @a,eq,#'&',incword
|
||
|
if2 @a,eq,#'|',incword
|
||
|
if2 @a,eq,#'<',incword
|
||
|
if2 @a,eq,#'>',incword
|
||
|
if2 @a,eq,#';',incword
|
||
|
bra nextword
|
||
|
incword inc count
|
||
|
nextword iny
|
||
|
bra illword
|
||
|
|
||
|
appword pei (word+2) ;append word to current command line
|
||
|
pei (word)
|
||
|
pei (cmdline+2)
|
||
|
pei (cmdline)
|
||
|
jsr cstrlen
|
||
|
tay
|
||
|
ldx argc
|
||
|
beq nospace
|
||
|
lda #' '
|
||
|
sta [cmdline],y
|
||
|
iny
|
||
|
nospace lda count
|
||
|
beq noquote
|
||
|
lda [word]
|
||
|
and #$FF
|
||
|
cmp #'"'
|
||
|
bne doquote
|
||
|
stz count
|
||
|
bra noquote
|
||
|
doquote lda #'"'
|
||
|
sta [cmdline],y
|
||
|
iny
|
||
|
inc count
|
||
|
noquote pei (cmdline+2)
|
||
|
add2 @y,cmdline,@a
|
||
|
pha
|
||
|
jsr copycstr
|
||
|
lda count
|
||
|
beq noquote2
|
||
|
pei (cmdline+2)
|
||
|
pei (cmdline)
|
||
|
jsr cstrlen
|
||
|
tay
|
||
|
lda #'"'
|
||
|
sta [cmdline],y
|
||
|
iny
|
||
|
lda #0
|
||
|
sta [cmdline],y
|
||
|
noquote2 inc argc ;increment argument count
|
||
|
goloop jmp loop
|
||
|
;
|
||
|
; Parse a '<' token
|
||
|
;
|
||
|
tok_lt lda srcfile
|
||
|
ora srcfile+2
|
||
|
beq lt1
|
||
|
lda #err02 ;Extra < encountered
|
||
|
jmp error
|
||
|
lt1 lda inpipe
|
||
|
beq lt2
|
||
|
lda #err09 ;< conflicts with |
|
||
|
jmp error
|
||
|
lt2 jsl alloc1024
|
||
|
stx srcfile+2
|
||
|
sta srcfile
|
||
|
phx
|
||
|
pha
|
||
|
pei (stream+2)
|
||
|
pei (stream)
|
||
|
jsl gettoken
|
||
|
if2 @a,eq,#T_WORD,goloop
|
||
|
lda #err03 ;Illegal < specified
|
||
|
jmp error
|
||
|
;
|
||
|
; Parse a '>' or '>>'
|
||
|
;
|
||
|
tok_gt anop
|
||
|
tok_gtgt lda dstfile
|
||
|
ora dstfile+2
|
||
|
beq gt1
|
||
|
lda #err04 ;Extra > or >> encountered
|
||
|
jmp error
|
||
|
gt1 jsl alloc1024
|
||
|
stx dstfile+2
|
||
|
sta dstfile
|
||
|
phx
|
||
|
pha
|
||
|
pei (stream+2)
|
||
|
pei (stream)
|
||
|
jsl gettoken
|
||
|
if2 @a,eq,#T_WORD,gt2
|
||
|
lda #err05 ;Illegal > or >> specified
|
||
|
jmp error
|
||
|
gt2 stz append
|
||
|
if2 token,ne,#T_GTGT,gt3
|
||
|
inc append
|
||
|
gt3 jmp loop
|
||
|
;
|
||
|
; Parse a '>&' or '>>&'
|
||
|
;
|
||
|
tok_gtamp anop
|
||
|
tok_gtgtamp lda errfile
|
||
|
ora errfile+2
|
||
|
beq ga1
|
||
|
lda #err06 ;Extra >& or >>& encountered
|
||
|
jmp error
|
||
|
ga1 jsl alloc1024
|
||
|
stx errfile+2
|
||
|
sta errfile
|
||
|
phx
|
||
|
pha
|
||
|
pei (stream+2)
|
||
|
pei (stream)
|
||
|
jsl gettoken
|
||
|
if2 @a,eq,#T_WORD,ga2
|
||
|
lda #err07 ;Illegal >& or >>& specified
|
||
|
jmp error
|
||
|
ga2 stz errappend
|
||
|
if2 token,ne,#T_GTGTAMP,ga3
|
||
|
inc errappend
|
||
|
ga3 jmp loop
|
||
|
;
|
||
|
; Parse a command terminator
|
||
|
;
|
||
|
tok_bar anop
|
||
|
tok_amp anop
|
||
|
tok_semi anop
|
||
|
tok_nl anop
|
||
|
tok_eof anop
|
||
|
|
||
|
lda argc ;terminate the argv list
|
||
|
bne nonnull
|
||
|
lda #0
|
||
|
sta [waitpid]
|
||
|
lda #T_NULL
|
||
|
jmp exit
|
||
|
nonnull asl2 a
|
||
|
tay
|
||
|
lda #0
|
||
|
sta [argv],y
|
||
|
iny2
|
||
|
sta [argv],y
|
||
|
;
|
||
|
; see if there is a conflict between >,>> with |
|
||
|
;
|
||
|
lda token
|
||
|
if2 @a,ne,#T_BAR,runit
|
||
|
lda dstfile
|
||
|
ora dstfile+2
|
||
|
beq bar2
|
||
|
lda #err08 ;> or >> conflicts with |
|
||
|
jmp error
|
||
|
|
||
|
bar2 clc
|
||
|
tdc
|
||
|
adc #pipefds
|
||
|
ldx #0
|
||
|
pipe @xa
|
||
|
;what if pipes return errors?
|
||
|
|
||
|
runit pei (argc)
|
||
|
pei (argv+2)
|
||
|
pei (argv)
|
||
|
pei (srcfile+2)
|
||
|
pei (srcfile)
|
||
|
pei (dstfile+2)
|
||
|
pei (dstfile)
|
||
|
pei (errfile+2)
|
||
|
pei (errfile)
|
||
|
pei (append)
|
||
|
pei (errappend)
|
||
|
ldx #0
|
||
|
if2 token,ne,#T_AMP,run2
|
||
|
inx
|
||
|
run2 phx
|
||
|
pei (cmdline+2)
|
||
|
pei (cmdline)
|
||
|
pei (jobflag)
|
||
|
pei (inpipe)
|
||
|
pei (pipefds+2)
|
||
|
pei (inpipe2)
|
||
|
pei (pipefds)
|
||
|
pei (pipesem+2)
|
||
|
pei (pipesem)
|
||
|
jsl invoke
|
||
|
sta pid
|
||
|
cmp #-1
|
||
|
beq exit
|
||
|
|
||
|
if2 token,ne,#T_BAR,run3
|
||
|
|
||
|
pei (waitpid+2)
|
||
|
pei (waitpid)
|
||
|
pei (pipefds)
|
||
|
pei (jobflag)
|
||
|
pei (pipefds+2)
|
||
|
pei (pipesem+2)
|
||
|
pei (pipesem)
|
||
|
pei (stream+2)
|
||
|
pei (stream)
|
||
|
jsl command
|
||
|
bra exit
|
||
|
|
||
|
run3 lda pid
|
||
|
sta [waitpid]
|
||
|
lda token
|
||
|
|
||
|
; clean up
|
||
|
|
||
|
exit pha
|
||
|
|
||
|
lda dstfile
|
||
|
ora dstfile+2
|
||
|
beq ex1
|
||
|
ldx dstfile+2
|
||
|
lda dstfile
|
||
|
jsl free1024
|
||
|
ex1 anop
|
||
|
|
||
|
lda srcfile
|
||
|
ora srcfile+2
|
||
|
beq ex2
|
||
|
ldx srcfile+2
|
||
|
lda srcfile
|
||
|
jsl free1024
|
||
|
ex2 anop
|
||
|
|
||
|
lda errfile
|
||
|
ora errfile+2
|
||
|
beq ex3
|
||
|
ldx errfile+2
|
||
|
lda errfile
|
||
|
jsl free1024
|
||
|
ex3 anop
|
||
|
|
||
|
ldx word+2
|
||
|
lda word
|
||
|
jsl free1024
|
||
|
|
||
|
ply
|
||
|
|
||
|
lda space
|
||
|
sta end-3
|
||
|
lda space+1
|
||
|
sta end-2
|
||
|
pld
|
||
|
tsc
|
||
|
clc
|
||
|
adc #end-4
|
||
|
tcs
|
||
|
|
||
|
tya
|
||
|
rtl
|
||
|
|
||
|
error ldx #^err00
|
||
|
jsr errputs
|
||
|
|
||
|
tok_error pei (cmdline+2)
|
||
|
pei (cmdline)
|
||
|
jsl nullfree
|
||
|
|
||
|
exit1a pei (argc)
|
||
|
pei (argv+2)
|
||
|
pei (argv)
|
||
|
jsl argfree
|
||
|
lda #-1
|
||
|
jmp exit
|
||
|
|
||
|
err00 dc c'gsh: Too many arguments, so no dessert tonight.',h'0d00'
|
||
|
err01 dc c'gsh: Not enough memory for arguments.',h'0d00'
|
||
|
err02 dc c'gsh: Extra ''<'' encountered.',h'0d00'
|
||
|
err03 dc c'gsh: No file specified for ''<''.',h'0d00'
|
||
|
err04 dc c'gsh: Extra ''>'' or ''>>'' encountered.',h'0d00'
|
||
|
err05 dc c'gsh: No file specified for ''>'' or ''>>''.',h'0d00'
|
||
|
err06 dc c'gsh: Extra ''>&'' or ''>>&'' encountered.',h'0d00'
|
||
|
err07 dc c'gsh: No file specified for ''>&'' or ''>>&''.',h'0d00'
|
||
|
err08 dc c'gsh: ''|'' conflicts with ''>'' or ''>>''.',h'0d00'
|
||
|
err09 dc c'gsh: ''|'' conflicts with ''<''.',h'0d00'
|
||
|
|
||
|
END
|
||
|
|
||
|
**************************************************************************
|
||
|
*
|
||
|
* dispose the argv
|
||
|
*
|
||
|
**************************************************************************
|
||
|
|
||
|
argfree START
|
||
|
|
||
|
space equ 0
|
||
|
|
||
|
subroutine (2:argc,4:argv),space
|
||
|
|
||
|
free1 lda argc
|
||
|
beq free2
|
||
|
dec a
|
||
|
asl2 a
|
||
|
tay
|
||
|
lda [argv],y
|
||
|
tax
|
||
|
iny2
|
||
|
lda [argv],y
|
||
|
pha
|
||
|
phx
|
||
|
jsl nullfree
|
||
|
dec argc
|
||
|
bra free1
|
||
|
free2 pei (argv+2)
|
||
|
pei (argv)
|
||
|
jsl nullfree
|
||
|
return
|
||
|
|
||
|
END
|
||
|
|
||
|
**************************************************************************
|
||
|
*
|
||
|
* Interpret a shell script
|
||
|
* This is overly complicated so that it can be run concurrently.
|
||
|
*
|
||
|
**************************************************************************
|
||
|
|
||
|
ShellExec START
|
||
|
|
||
|
using vardata
|
||
|
using global
|
||
|
|
||
|
count equ 1
|
||
|
data equ count+2
|
||
|
CRec equ data+4
|
||
|
RRec equ CRec+4
|
||
|
NRec equ RRec+4
|
||
|
ORec equ NRec+4
|
||
|
ptr equ ORec+4
|
||
|
space equ ptr+4
|
||
|
jobflag equ space+3
|
||
|
argv equ jobflag+2
|
||
|
argc equ argv+4
|
||
|
path equ argc+2
|
||
|
end equ path+4
|
||
|
|
||
|
; subroutine (4:path,2:argc,4:argv,2:jobflag),space
|
||
|
|
||
|
tsc
|
||
|
sec
|
||
|
sbc #space-1
|
||
|
tcs
|
||
|
phd
|
||
|
tcd
|
||
|
|
||
|
wait ldy mutex
|
||
|
beq wait0
|
||
|
cop $7F
|
||
|
bra wait
|
||
|
wait0 inc mutex
|
||
|
;
|
||
|
; set the variables 0..argc
|
||
|
;
|
||
|
lda argc
|
||
|
jeq skipvar
|
||
|
stz count
|
||
|
parmloop lda count
|
||
|
asl2 a
|
||
|
tay
|
||
|
lda [argv],y
|
||
|
sta setparm+4
|
||
|
iny2
|
||
|
lda [argv],y
|
||
|
sta setparm+6
|
||
|
lda count
|
||
|
cmp #10
|
||
|
bcs num1
|
||
|
short a
|
||
|
adc #'0'
|
||
|
sta num+2
|
||
|
long a
|
||
|
ld4 num+2,setparm
|
||
|
bra setit
|
||
|
num1 cmp #100
|
||
|
bcs num2
|
||
|
Int2Dec (@a,#num+1,#2,#0)
|
||
|
ld4 num+1,setparm
|
||
|
bra setit
|
||
|
num2 Int2Dec (@a,#num,#3,#0)
|
||
|
ld4 num,setparm
|
||
|
setit ph4 setparm
|
||
|
jsr c2pstr2
|
||
|
phx
|
||
|
pha
|
||
|
stx setparm+2
|
||
|
sta setparm
|
||
|
ph4 setparm+4
|
||
|
jsr c2pstr2
|
||
|
phx
|
||
|
pha
|
||
|
stx setparm+4+2
|
||
|
sta setparm+4
|
||
|
Set_Variable setparm
|
||
|
jsl nullfree
|
||
|
jsl nullfree
|
||
|
inc count
|
||
|
lda count
|
||
|
cmp argc
|
||
|
jcc parmloop
|
||
|
|
||
|
skipvar dec mutex
|
||
|
|
||
|
ph4 #4 ;Close parms
|
||
|
jsl ~NEW
|
||
|
sta CRec
|
||
|
stx CRec+2
|
||
|
|
||
|
ph4 #10 ;Open parms
|
||
|
jsl ~NEW
|
||
|
sta ORec
|
||
|
stx ORec+2
|
||
|
|
||
|
ph4 #12 ;NewLine parms
|
||
|
jsl ~NEW
|
||
|
sta NRec
|
||
|
stx NRec+2
|
||
|
|
||
|
ph4 #16 ;Read parms
|
||
|
jsl ~NEW
|
||
|
sta RRec
|
||
|
stx RRec+2
|
||
|
|
||
|
ph4 #1000 ;data buffer
|
||
|
jsl ~NEW
|
||
|
sta data
|
||
|
stx data+2
|
||
|
|
||
|
pei (path+2) ;Convert filename to GS/OS string
|
||
|
pei (path)
|
||
|
jsr c2gsstr
|
||
|
ldy #4
|
||
|
sta [ORec],y
|
||
|
sta ptr
|
||
|
iny2
|
||
|
txa
|
||
|
sta [ORec],y
|
||
|
sta ptr+2
|
||
|
|
||
|
ldy #8
|
||
|
lda #1 ;Read access only
|
||
|
sta [ORec],y
|
||
|
|
||
|
lda #3 ;Open the file
|
||
|
sta [ORec]
|
||
|
pei (ORec+2)
|
||
|
pei (ORec)
|
||
|
ph2 #$2010 ;OPEN
|
||
|
jsl $E100B0
|
||
|
bcc ok
|
||
|
sta Err
|
||
|
Error Err
|
||
|
jmp done
|
||
|
awshit sta Err
|
||
|
Error Err
|
||
|
jmp almostdone
|
||
|
|
||
|
ok ldy #2 ;Copy file ref num
|
||
|
lda [ORec],y
|
||
|
sta [NRec],y
|
||
|
sta [RRec],y
|
||
|
sta [CRec],y
|
||
|
|
||
|
lda #4 ;Do NewLine
|
||
|
sta [NRec]
|
||
|
ldy #4
|
||
|
lda #$7F
|
||
|
sta [NRec],y
|
||
|
iny2
|
||
|
lda #1
|
||
|
sta [NRec],y
|
||
|
iny2
|
||
|
lda #NLTable
|
||
|
sta [NRec],y
|
||
|
iny2
|
||
|
lda #^NLTable
|
||
|
sta [NRec],y
|
||
|
pei (NRec+2)
|
||
|
pei (NRec)
|
||
|
ph2 #$2011 ;NEWLINE
|
||
|
jsl $E100B0
|
||
|
bcs awshit
|
||
|
|
||
|
lda #4 ;Set up read parm
|
||
|
sta [RRec]
|
||
|
tay
|
||
|
lda data
|
||
|
sta [RRec],y
|
||
|
iny2
|
||
|
lda data+2
|
||
|
sta [RRec],y
|
||
|
iny2
|
||
|
lda #1000
|
||
|
sta [RRec],y
|
||
|
iny2
|
||
|
lda #0
|
||
|
sta [RRec],y
|
||
|
|
||
|
ReadLoop anop
|
||
|
pei (RRec+2)
|
||
|
pei (RRec)
|
||
|
ph2 #$2012 ;READ
|
||
|
jsl $E100B0
|
||
|
bcs almostdone
|
||
|
ldy #12
|
||
|
lda [RRec],y
|
||
|
tay
|
||
|
lda #0
|
||
|
sta [data],y
|
||
|
lda varecho
|
||
|
beq noecho
|
||
|
ldx data+2
|
||
|
lda data
|
||
|
jsr puts
|
||
|
jsr newline
|
||
|
noecho lda [data]
|
||
|
and #$FF
|
||
|
if2 @a,eq,#'#',ReadLoop
|
||
|
pei (data+2)
|
||
|
pei (data)
|
||
|
* ph2 #0
|
||
|
* ph2 #1
|
||
|
pei (jobflag)
|
||
|
jsl execute
|
||
|
lda exitamundo
|
||
|
bne almostdone
|
||
|
bra ReadLoop
|
||
|
|
||
|
almostdone anop
|
||
|
stz exitamundo
|
||
|
lda #1
|
||
|
sta [CRec]
|
||
|
pei (CRec+2)
|
||
|
pei (CRec)
|
||
|
ph2 #$2014 ;CLOSE
|
||
|
jsl $E100B0
|
||
|
|
||
|
done pei (CRec+2)
|
||
|
pei (CRec)
|
||
|
jsl nullfree
|
||
|
pei (NRec+2)
|
||
|
pei (NRec)
|
||
|
jsl nullfree
|
||
|
pei (RRec+2)
|
||
|
pei (RRec)
|
||
|
jsl nullfree
|
||
|
pei (ORec+2)
|
||
|
pei (ORec)
|
||
|
jsl nullfree
|
||
|
pei (data+2)
|
||
|
pei (data)
|
||
|
jsl nullfree
|
||
|
pei (ptr+2)
|
||
|
pei (ptr)
|
||
|
jsl nullfree
|
||
|
|
||
|
exit1a anop
|
||
|
|
||
|
lda space+1
|
||
|
sta end-2
|
||
|
lda space
|
||
|
sta end-3
|
||
|
pld
|
||
|
tsc
|
||
|
clc
|
||
|
adc #end-4
|
||
|
tcs
|
||
|
rtl
|
||
|
|
||
|
NLTable dc h'0d'
|
||
|
|
||
|
Err ds 2
|
||
|
|
||
|
setparm ds 4
|
||
|
ds 4
|
||
|
num dc c'000',h'00'
|
||
|
|
||
|
mutex dc i'0'
|
||
|
|
||
|
END
|
||
|
|
||
|
**************************************************************************
|
||
|
*
|
||
|
* Execute a command line by calling command for each command in the buffer
|
||
|
*
|
||
|
**************************************************************************
|
||
|
|
||
|
execute START
|
||
|
|
||
|
exebuf equ 1
|
||
|
pipesem equ exebuf+4
|
||
|
ptr2 equ pipesem+2
|
||
|
waitstatus equ ptr2+4
|
||
|
ptr equ waitstatus+2
|
||
|
pid equ ptr+4
|
||
|
term equ pid+2
|
||
|
space equ term+2
|
||
|
jobflag equ space+3 ;set if not a job
|
||
|
cmdline equ jobflag+2
|
||
|
end equ cmdline+4
|
||
|
|
||
|
; subroutine (4:cmdline,2:jobflag),space
|
||
|
|
||
|
tsc
|
||
|
sec
|
||
|
sbc #space-1
|
||
|
tcs
|
||
|
phd
|
||
|
tcd
|
||
|
|
||
|
stz pipesem
|
||
|
stz waitstatus
|
||
|
|
||
|
pei (cmdline+2)
|
||
|
pei (cmdline)
|
||
|
jsl expandvars
|
||
|
phx
|
||
|
pha
|
||
|
sta ptr
|
||
|
stx ptr+2
|
||
|
jsl glob
|
||
|
phx
|
||
|
pha
|
||
|
sta ptr2
|
||
|
stx ptr2+2
|
||
|
jsl expandalias
|
||
|
phx
|
||
|
pha
|
||
|
sta exebuf
|
||
|
stx exebuf+2
|
||
|
ldx ptr+2
|
||
|
lda ptr
|
||
|
jsl free1024
|
||
|
ldx ptr2+2
|
||
|
lda ptr2
|
||
|
jsl free1024
|
||
|
|
||
|
lda exebuf
|
||
|
ora exebuf+2
|
||
|
bne loop
|
||
|
|
||
|
pla
|
||
|
pla
|
||
|
stz term
|
||
|
lda #0
|
||
|
jmp ouch
|
||
|
|
||
|
loop pea 0 ;Bank 0
|
||
|
tdc
|
||
|
clc
|
||
|
adc #pid
|
||
|
pha
|
||
|
pea 0
|
||
|
pei (jobflag)
|
||
|
pea 0
|
||
|
pea 0 ;Bank 0
|
||
|
tdc
|
||
|
clc
|
||
|
adc #pipesem
|
||
|
pha
|
||
|
pea 0 ;Bank 0
|
||
|
tdc
|
||
|
clc
|
||
|
adc #exebuf
|
||
|
pha
|
||
|
jsl command
|
||
|
sta term
|
||
|
bmi noerrexit
|
||
|
|
||
|
lda pid
|
||
|
beq nowait
|
||
|
cmp #-1
|
||
|
beq noerrexit
|
||
|
|
||
|
lda jobflag
|
||
|
beq jobwait
|
||
|
|
||
|
signal (#SIGINT,#0)
|
||
|
phx
|
||
|
pha
|
||
|
signal (#SIGSTOP,#0)
|
||
|
phx
|
||
|
pha
|
||
|
|
||
|
otherwait ldx #0
|
||
|
clc
|
||
|
tdc
|
||
|
adc #waitstatus
|
||
|
wait @xa
|
||
|
cmp pid
|
||
|
bne otherwait
|
||
|
lda waitstatus
|
||
|
and #$FF
|
||
|
cmp #$7F
|
||
|
beq otherwait
|
||
|
lda waitstatus
|
||
|
jsr setstatus
|
||
|
|
||
|
pla
|
||
|
plx
|
||
|
signal (#SIGSTOP,@xa)
|
||
|
pla
|
||
|
plx
|
||
|
signal (#SIGINT,@xa)
|
||
|
|
||
|
bra nowait
|
||
|
|
||
|
jobwait jsl pwait
|
||
|
sta waitstatus
|
||
|
|
||
|
nowait if2 term,eq,#T_EOF,noerrexit
|
||
|
lda [exebuf]
|
||
|
and #$FF
|
||
|
beq exit
|
||
|
jmp loop
|
||
|
|
||
|
noerrexit stz waitstatus ;non-forked builtins cannot return an error
|
||
|
exit jsl nullfree
|
||
|
lda term ;make sure we return -1 if error
|
||
|
bmi ouch
|
||
|
|
||
|
lda waitstatus
|
||
|
xba
|
||
|
and #$FF
|
||
|
ouch tay
|
||
|
lda space+1
|
||
|
sta end-2
|
||
|
lda space
|
||
|
sta end-3
|
||
|
pld
|
||
|
tsc
|
||
|
clc
|
||
|
adc #end-4
|
||
|
tcs
|
||
|
|
||
|
tya
|
||
|
rtl
|
||
|
|
||
|
END
|
||
|
|
||
|
**************************************************************************
|
||
|
*
|
||
|
* System() call vector
|
||
|
*
|
||
|
**************************************************************************
|
||
|
|
||
|
system START
|
||
|
|
||
|
retval equ 0
|
||
|
space equ retval+2
|
||
|
|
||
|
subroutine (4:str),space ;need the phk/plb
|
||
|
|
||
|
pei (str+2)
|
||
|
pei (str)
|
||
|
ph2 #1 ;tells execute we're called by system
|
||
|
jsl execute
|
||
|
sta retval
|
||
|
|
||
|
return 2:retval
|
||
|
|
||
|
END
|