Merge pull request #31 from philbudne/master
more shell work; renamed sh.s to pbsh.s
This commit is contained in:
@@ -0,0 +1,434 @@
|
|||||||
|
" -*-fundamental-*-
|
||||||
|
" sh -- a shell
|
||||||
|
" started by p budne 3/4/2016
|
||||||
|
" with code from cat.s, init.s, and looking at the v1 (pdp-11) shell
|
||||||
|
|
||||||
|
" XXX cat.s seems to write error output on fd 8
|
||||||
|
|
||||||
|
start:
|
||||||
|
" XXX take command line argument (script file to open), suppress prompt??
|
||||||
|
" NOTE!!! v0 init.s doesn't set up the argv at the top of memory,
|
||||||
|
" so the v0 shell may not have taken command line arguments!!!
|
||||||
|
" if non-interactive, "dzm prompt", jump to newcom
|
||||||
|
|
||||||
|
interactive:
|
||||||
|
-1
|
||||||
|
sys intrp " make shell uninterruptable
|
||||||
|
sys getuid
|
||||||
|
sma " <0?
|
||||||
|
jmp newline " no, a mundane
|
||||||
|
lac hash " yes: superuser
|
||||||
|
dac prompt " change prompt
|
||||||
|
|
||||||
|
newline:
|
||||||
|
lac d1; sys write; prompt; 1 " output prompt
|
||||||
|
newcom:
|
||||||
|
dzm char " clear saved char
|
||||||
|
dzm infile " clear input redirect file name
|
||||||
|
dzm outfile " clear output redirect file name
|
||||||
|
lac iopt " reset output pointer
|
||||||
|
dac opt
|
||||||
|
dac nextarg
|
||||||
|
|
||||||
|
" reset high memory
|
||||||
|
dzm argc " clear arg count
|
||||||
|
lac argcptr
|
||||||
|
dac argptr
|
||||||
|
dzm argv0 " clear out argv0 for chdir comparison
|
||||||
|
dzm argv0+1
|
||||||
|
dzm argv0+2
|
||||||
|
|
||||||
|
newarg:
|
||||||
|
-8 " save 8 chars
|
||||||
|
dac bcount
|
||||||
|
dzm redirect
|
||||||
|
|
||||||
|
lac opt " save start for print (TEMP)
|
||||||
|
dac nextarg
|
||||||
|
|
||||||
|
jms blank " skip whitespace
|
||||||
|
jms delim " newline?
|
||||||
|
jmp eol " yes
|
||||||
|
sad lt " input redirect?
|
||||||
|
jmp redirin
|
||||||
|
sad gt " output redirect?
|
||||||
|
jmp redirout
|
||||||
|
jmp 3f
|
||||||
|
|
||||||
|
redirin: " saw <
|
||||||
|
dac redirect " flag redirect
|
||||||
|
lac infilep
|
||||||
|
dac opt
|
||||||
|
jmp newchar " v1 behavior? no whitespace eater
|
||||||
|
|
||||||
|
redirout: " saw >
|
||||||
|
dac redirect " flag redirect
|
||||||
|
lac outfilep
|
||||||
|
dac opt
|
||||||
|
" v1 behavior? no whitespace eater!
|
||||||
|
" fall
|
||||||
|
|
||||||
|
newchar:
|
||||||
|
jms getc
|
||||||
|
sad o40 " space?
|
||||||
|
jmp ws " yes
|
||||||
|
jms delim
|
||||||
|
jmp eoname
|
||||||
|
3: jms putc " save
|
||||||
|
isz bcount " loop unless full
|
||||||
|
jmp newchar
|
||||||
|
|
||||||
|
" here after 8 chars: discard until terminator seen
|
||||||
|
discard:
|
||||||
|
jms getc
|
||||||
|
dac char
|
||||||
|
sad o4
|
||||||
|
jmp eof
|
||||||
|
jms delim " end of line?
|
||||||
|
jmp eoname
|
||||||
|
sad o40
|
||||||
|
jmp eoname
|
||||||
|
jmp discard
|
||||||
|
|
||||||
|
" here with EOF in command: process command?
|
||||||
|
eof:
|
||||||
|
sys exit " quit, for now?
|
||||||
|
|
||||||
|
" name ended (short) with whitespace or newline
|
||||||
|
" pad out last name to 8 with spaces
|
||||||
|
ws:
|
||||||
|
dac char " save terminator
|
||||||
|
1: lac o40
|
||||||
|
jms putc " no: copy into argv
|
||||||
|
isz bcount " loop until full
|
||||||
|
jmp 1b
|
||||||
|
|
||||||
|
" saw end of name
|
||||||
|
eoname:
|
||||||
|
dac char
|
||||||
|
lac redirect
|
||||||
|
sza
|
||||||
|
jmp 2f " last name was a redirect file, skip increment
|
||||||
|
|
||||||
|
lac argc " increment argc
|
||||||
|
tad d4
|
||||||
|
dac argc
|
||||||
|
lac nextarg
|
||||||
|
tad d4 " advance nextarg
|
||||||
|
dac nextarg
|
||||||
|
|
||||||
|
2:
|
||||||
|
dzm redirect " clear redirect flag
|
||||||
|
lac nextarg
|
||||||
|
dac opt
|
||||||
|
|
||||||
|
lac char
|
||||||
|
jms delim
|
||||||
|
jmp eol
|
||||||
|
|
||||||
|
-maxargs
|
||||||
|
tad argc
|
||||||
|
sza
|
||||||
|
jmp newarg
|
||||||
|
|
||||||
|
" too many args, (complain?). for now eat rest of line
|
||||||
|
4: jms getc
|
||||||
|
jms delim
|
||||||
|
skp
|
||||||
|
jmp 4b
|
||||||
|
lac d1; sys write; toomany; ltoomany
|
||||||
|
jmp newline
|
||||||
|
|
||||||
|
" here at end of line
|
||||||
|
eol:
|
||||||
|
sad delimchar " save eol character
|
||||||
|
lac argc " check for empty command line
|
||||||
|
sna " get anything?
|
||||||
|
jmp 2f " no, go back for another
|
||||||
|
|
||||||
|
" check for built-in "chdir" command
|
||||||
|
lac argv0
|
||||||
|
sad chdirstr
|
||||||
|
skp
|
||||||
|
jmp 1f
|
||||||
|
lac argv0+1
|
||||||
|
sad chdirstr+1
|
||||||
|
skp
|
||||||
|
jmp 1f
|
||||||
|
lac argv0+2
|
||||||
|
sad chdirstr+2
|
||||||
|
jmp changedir
|
||||||
|
|
||||||
|
1:
|
||||||
|
" comment these out to test "exec"
|
||||||
|
sys fork
|
||||||
|
jmp parent
|
||||||
|
|
||||||
|
" here in child
|
||||||
|
lac d2; sys close " close fd 2
|
||||||
|
sys unlink; exectemp " remove temp file
|
||||||
|
|
||||||
|
" try to link binary from "system" directory to "exectemp" file
|
||||||
|
" sys link; system; argv0; exectemp
|
||||||
|
" spa
|
||||||
|
" jmp notsys
|
||||||
|
" sys open; exectemp; 0
|
||||||
|
" spa
|
||||||
|
" jmp error
|
||||||
|
" sys unlink; exectemp
|
||||||
|
" jmp 1f
|
||||||
|
"notsys: " not found in "system"
|
||||||
|
|
||||||
|
sys open; argv0; 0 " try cwd
|
||||||
|
spa
|
||||||
|
jmp cmderr
|
||||||
|
|
||||||
|
cla " check for input redirection
|
||||||
|
sad infile
|
||||||
|
jmp 1f
|
||||||
|
sys close " close fd 0
|
||||||
|
sys open; infile; 0 " open redirected
|
||||||
|
spa sna
|
||||||
|
jmp inerror
|
||||||
|
cla
|
||||||
|
1: sad outfile
|
||||||
|
jmp exec
|
||||||
|
lac d1; sys close " close fd 1
|
||||||
|
lac o17
|
||||||
|
sys creat; outfile " open output redirect
|
||||||
|
spa
|
||||||
|
jmp outerror
|
||||||
|
|
||||||
|
" here to "exec" file open on fd 2, adapted from init.s
|
||||||
|
exec:
|
||||||
|
law boot-1 " Get source addr
|
||||||
|
dac 8 " set up index 8 (pre-increments)
|
||||||
|
law bootloc-1 " Copy "boot" code into high memory
|
||||||
|
dac 9 " set up index 9 (pre-increments)
|
||||||
|
1: lac 8 i
|
||||||
|
dac 9 i
|
||||||
|
isz bootcount " can only do this once!
|
||||||
|
jmp 1b
|
||||||
|
jmp bootloc " and then jump to the code
|
||||||
|
|
||||||
|
" copied up to bootloc in high memory (below argc)
|
||||||
|
boot:
|
||||||
|
lac d2 " Load fd 2 (the opened executable)
|
||||||
|
lmq " Save the fd into MQ
|
||||||
|
sys read; userbase; userlen " read executable in
|
||||||
|
lacq " Get the fd back and close the file
|
||||||
|
sys close
|
||||||
|
jmp userbase " and jump to the beginning of the executable
|
||||||
|
bootlen=.-boot " length of bootstrap
|
||||||
|
|
||||||
|
bootcount: -bootlen " isz loop count for bootstrap copy
|
||||||
|
|
||||||
|
" error in child process:
|
||||||
|
inerror: " error opening input redirection
|
||||||
|
lac infilep
|
||||||
|
jmp error
|
||||||
|
outerror: " error opening new stdout (stdout closed!)
|
||||||
|
lac outfilep
|
||||||
|
skp
|
||||||
|
cmderr: " error opening command
|
||||||
|
lac argv0p
|
||||||
|
error: " error in child: filename pointer in AC
|
||||||
|
dac 1f " save filename to complain about
|
||||||
|
lac d1; sys write; 1: 0; 4
|
||||||
|
lac d1; sys write; qmnl; 1
|
||||||
|
lac d2; sys close
|
||||||
|
sys exit
|
||||||
|
|
||||||
|
" chdir command: executed in shell process
|
||||||
|
changedir:
|
||||||
|
" XXX check if argc == 4 (no directories) and complain??
|
||||||
|
lac argv0p
|
||||||
|
skp
|
||||||
|
1: lac 0f " increment argvp
|
||||||
|
tad d4
|
||||||
|
sad 0f
|
||||||
|
-4 " decrement argc
|
||||||
|
tad argc
|
||||||
|
dac argc
|
||||||
|
sna " done?
|
||||||
|
jmp 2f " yes: join parent code
|
||||||
|
sys chdir; 0:0
|
||||||
|
sma " error?
|
||||||
|
jmp 1b " no: look for another directory
|
||||||
|
|
||||||
|
" chdir call failed
|
||||||
|
lac 0b
|
||||||
|
dac 0f
|
||||||
|
lac d1; sys write; 0:0; 4
|
||||||
|
lac d1; sys write; qmnl; 1
|
||||||
|
jmp 2f " join parent code
|
||||||
|
|
||||||
|
" here in parent, child pid in AC
|
||||||
|
parent:
|
||||||
|
" https://www.bell-labs.com/usr/dmr/www/hist.html
|
||||||
|
" The message facility was used as follows: the parent shell, after
|
||||||
|
" creating a process to execute a command, sent a message to the new
|
||||||
|
" process by smes; when the command terminated (assuming it did not
|
||||||
|
" try to read any messages) the shell's blocked smes call returned an
|
||||||
|
" error indication that the target process did not exist. Thus the
|
||||||
|
" shell's smes became, in effect, the equivalent of wait.
|
||||||
|
dac pid
|
||||||
|
lac delimchar
|
||||||
|
sad o46 " ampersand?
|
||||||
|
jmp newcom " yes: go back without wait
|
||||||
|
lac pid
|
||||||
|
sys smes " hang until child exits
|
||||||
|
2: lac delimchar
|
||||||
|
sad o73 " semi?
|
||||||
|
jmp newcom " yes: look for another command w/o prompt
|
||||||
|
jmp newline " no: output prompt
|
||||||
|
|
||||||
|
" ================
|
||||||
|
" subroutines
|
||||||
|
|
||||||
|
" eat spaces
|
||||||
|
" v1 routine name:
|
||||||
|
blank: 0
|
||||||
|
1: jms getc
|
||||||
|
sad o40
|
||||||
|
jmp 1b
|
||||||
|
jmp blank i
|
||||||
|
|
||||||
|
" give skip return if AC *NOT* a command delimiter
|
||||||
|
" v1 routine name:
|
||||||
|
delim: 0
|
||||||
|
sad o12 " newline
|
||||||
|
jmp delim i
|
||||||
|
sad o46 " ampersand
|
||||||
|
jmp delim i
|
||||||
|
sad o73 " semi
|
||||||
|
jmp delim i
|
||||||
|
isz delim " ran the gauntlet: skip home
|
||||||
|
jmp delim i
|
||||||
|
|
||||||
|
" from cat.s
|
||||||
|
getc: 0
|
||||||
|
lac ipt " Load pointer to next word in the buffer
|
||||||
|
sad eipt
|
||||||
|
jmp 1f " end of the buffer, so read more
|
||||||
|
dac 2f " Save the pointer
|
||||||
|
add o400000 " flip MSB, increment pointer on overflow
|
||||||
|
dac ipt
|
||||||
|
ral " Move the msb into the link register
|
||||||
|
lac 2f i " Load the word from the buffer
|
||||||
|
szl " Skip if second character in word
|
||||||
|
lrss 9 " first char: shift down the top character
|
||||||
|
and o177 " Keep the lowest 7 bits
|
||||||
|
sna
|
||||||
|
jmp getc+1 " Skip a NUL characters and read another one
|
||||||
|
jmp getc i " Return the character from the subroutine
|
||||||
|
|
||||||
|
1:
|
||||||
|
cla " Buffer is empty, read another 64 characters
|
||||||
|
sys read; ibuf; 64
|
||||||
|
sna
|
||||||
|
jmp 1f " No characters were read in
|
||||||
|
tad iipt " Add the word count to the base of the buffer
|
||||||
|
dac eipt " and store in the end buffer pointer
|
||||||
|
lac iipt " Reset the ipt to the base of the buffer
|
||||||
|
dac ipt
|
||||||
|
jmp getc+1 " and loop back to get one character
|
||||||
|
1:
|
||||||
|
lac o4 " No character, return with ctrl-D
|
||||||
|
jmp getc i " return from subroutine
|
||||||
|
|
||||||
|
putc: 0
|
||||||
|
and o177 " Keep the lowest 7 bits and save into 2f+1
|
||||||
|
dac 2f+1
|
||||||
|
lac opt " Save the pointer to the empty buffer
|
||||||
|
dac 2f " position to 2f
|
||||||
|
add o400000 " Flip the msb and save back into opt
|
||||||
|
dac opt " This also has the effect of incrementing
|
||||||
|
" the opt pointer every second addition!
|
||||||
|
|
||||||
|
spa " If the bit was set, we already have one
|
||||||
|
jmp 1f " character at 2f+1. If no previous character,
|
||||||
|
lac 2f i " merge the old and new character together
|
||||||
|
xor 2f+1
|
||||||
|
jmp 3f " and go to the "save it in buffer" code
|
||||||
|
1:
|
||||||
|
lac 2f+1 " Move the character up into the top half
|
||||||
|
alss 9
|
||||||
|
3:
|
||||||
|
dac 2f i " Save the word into the buffer
|
||||||
|
jmp putc i " No, so return (more room still in the buffer)
|
||||||
|
|
||||||
|
2: 0;0 " Current input and output word pointers
|
||||||
|
ipt: 0 " Current input buffer base
|
||||||
|
eipt: 0 " Pointer to end of data read in input buffer
|
||||||
|
iipt: ibuf
|
||||||
|
ibuf: .=.+64
|
||||||
|
|
||||||
|
" literals
|
||||||
|
d1: 1
|
||||||
|
d2: 2
|
||||||
|
o4:d4: 4
|
||||||
|
o12: 012 " newline
|
||||||
|
o17: 017
|
||||||
|
o40: 040 " space
|
||||||
|
o46: 046 " ampersand
|
||||||
|
o73: 046 " semi
|
||||||
|
o74:lt: 074 " <
|
||||||
|
o76:gt: 076 " >
|
||||||
|
o177: 0177 " 7-bit (ASCII) mask
|
||||||
|
o400000: 0400000 " MSB
|
||||||
|
|
||||||
|
hash: <#> " superuser prompt
|
||||||
|
qmnl: <? 012 " question mark, newline
|
||||||
|
|
||||||
|
system:
|
||||||
|
<sy>;<st>;<em>; 040040
|
||||||
|
|
||||||
|
exectemp:
|
||||||
|
<ex>;<ec>;<te>;<mp> " temporary link for file being exec'ed
|
||||||
|
|
||||||
|
chdirstr:
|
||||||
|
<ch>;<di>;<r 040
|
||||||
|
|
||||||
|
" TEMP FOR DEBUG:
|
||||||
|
star: <*> "
|
||||||
|
|
||||||
|
toomany: <to>;<o> ;<ma>;<ny>;< a>;<rg>;<s 012
|
||||||
|
ltoomany=.-toomany
|
||||||
|
|
||||||
|
" ################ variables
|
||||||
|
|
||||||
|
prompt: <@> " v1 prompt
|
||||||
|
pid: 0 " "other" pid
|
||||||
|
char: 0 " white space char
|
||||||
|
redirect: 0 " last file was a redirect (lt or gt)
|
||||||
|
bcount: 0 " byte counter for current filename
|
||||||
|
delimchar: 0 " character that terminated line
|
||||||
|
|
||||||
|
iopt:argv0p: argv0 " initial value for nextarg, opt
|
||||||
|
nextarg: 0 " next slot in argv to fill
|
||||||
|
opt: 0 " "output pointer" (may point to in/outfile)
|
||||||
|
|
||||||
|
infilep: infile
|
||||||
|
outfilep: outfile
|
||||||
|
|
||||||
|
outfile: .=.+4 " buffer for output redirect file name
|
||||||
|
infile: .=.+4 " buffer for input redirect file name
|
||||||
|
|
||||||
|
argcptr: argc
|
||||||
|
|
||||||
|
" leave room for maxargs items of 4 words each
|
||||||
|
maxargs=8
|
||||||
|
|
||||||
|
userbase=010000 " user starts at 4K
|
||||||
|
argptr=017777 " last word points to argc + argv data
|
||||||
|
argc=argptr-maxargs-maxargs-maxargs-maxargs-1 " argc followed by argv
|
||||||
|
|
||||||
|
" arguments in 4 word blocks follow argc
|
||||||
|
argv0=argc+1
|
||||||
|
|
||||||
|
" "bootstrap" (reads executable into userbase) JUST below argc
|
||||||
|
bootloc=argc-bootlen " location of bootstrap
|
||||||
|
|
||||||
|
userlen=bootloc-userbase " max executable
|
||||||
|
|
||||||
+134
-109
@@ -3,6 +3,8 @@
|
|||||||
" started by p budne 3/4/2016
|
" started by p budne 3/4/2016
|
||||||
" with code from cat.s, init.s, and looking at the v1 (pdp-11) shell
|
" with code from cat.s, init.s, and looking at the v1 (pdp-11) shell
|
||||||
|
|
||||||
|
" XXX cat.s seems to write error output on fd 8
|
||||||
|
|
||||||
start:
|
start:
|
||||||
" XXX take command line argument (script file to open), suppress prompt??
|
" XXX take command line argument (script file to open), suppress prompt??
|
||||||
" NOTE!!! v0 init.s doesn't set up the argv at the top of memory,
|
" NOTE!!! v0 init.s doesn't set up the argv at the top of memory,
|
||||||
@@ -21,30 +23,31 @@ interactive:
|
|||||||
newline:
|
newline:
|
||||||
lac d1; sys write; prompt; 1 " output prompt
|
lac d1; sys write; prompt; 1 " output prompt
|
||||||
newcom:
|
newcom:
|
||||||
dzm argc " clear arg count
|
|
||||||
dzm char " clear saved char
|
dzm char " clear saved char
|
||||||
dzm infile " clear input redirect file name
|
dzm infile " clear input redirect file name
|
||||||
dzm outfile " clear output redirect file name
|
dzm outfile " clear output redirect file name
|
||||||
dzm argv0 " clear out argv0 for chdir comparison
|
|
||||||
dzm argv0+1
|
|
||||||
dzm argv0+2
|
|
||||||
lac argcptr
|
|
||||||
dac argptr
|
|
||||||
lac iopt " reset output pointer
|
lac iopt " reset output pointer
|
||||||
dac opt
|
dac opt
|
||||||
dac nextarg
|
dac nextarg
|
||||||
|
|
||||||
|
" reset high memory
|
||||||
|
dzm argc " clear arg count
|
||||||
|
lac argcptr
|
||||||
|
dac argptr
|
||||||
|
dzm argv0 " clear out argv0 for chdir comparison
|
||||||
|
dzm argv0+1
|
||||||
|
dzm argv0+2
|
||||||
|
|
||||||
newarg:
|
newarg:
|
||||||
-8 " save 8 chars
|
-8 " save 8 chars
|
||||||
dac bcount
|
dac bcount
|
||||||
dzm redirect
|
dzm redirect
|
||||||
|
|
||||||
lac opt " save start for print (TEMP)
|
lac opt " save start for print (TEMP)
|
||||||
dac 8f
|
|
||||||
dac nextarg
|
dac nextarg
|
||||||
|
|
||||||
jms blank " skip whitespace
|
jms blank " skip whitespace
|
||||||
sad o12 " newline?
|
jms delim " newline?
|
||||||
jmp eol " yes
|
jmp eol " yes
|
||||||
sad lt " input redirect?
|
sad lt " input redirect?
|
||||||
jmp redirin
|
jmp redirin
|
||||||
@@ -56,23 +59,21 @@ redirin: " saw <
|
|||||||
dac redirect " flag redirect
|
dac redirect " flag redirect
|
||||||
lac infilep
|
lac infilep
|
||||||
dac opt
|
dac opt
|
||||||
dac 8f " TEMP
|
|
||||||
jmp newchar " v1 behavior? no whitespace eater
|
jmp newchar " v1 behavior? no whitespace eater
|
||||||
|
|
||||||
redirout: " saw >
|
redirout: " saw >
|
||||||
dac redirect " flag redirect
|
dac redirect " flag redirect
|
||||||
lac outfilep
|
lac outfilep
|
||||||
dac opt
|
dac opt
|
||||||
dac 8f " TEMP
|
" v1 behavior? no whitespace eater!
|
||||||
" v1 behavior? no whitespace eater
|
|
||||||
" fall
|
" fall
|
||||||
|
|
||||||
newchar:
|
newchar:
|
||||||
jms getc
|
jms getc
|
||||||
sad o40 " space?
|
sad o40 " space?
|
||||||
jmp ws " yes
|
jmp ws " yes
|
||||||
sad o12
|
jms delim
|
||||||
jmp ws
|
jmp eoname
|
||||||
3: jms putc " save
|
3: jms putc " save
|
||||||
isz bcount " loop unless full
|
isz bcount " loop unless full
|
||||||
jmp newchar
|
jmp newchar
|
||||||
@@ -83,20 +84,20 @@ discard:
|
|||||||
dac char
|
dac char
|
||||||
sad o4
|
sad o4
|
||||||
jmp eof
|
jmp eof
|
||||||
sad o12
|
jms delim " end of line?
|
||||||
jmp eoname
|
jmp eoname
|
||||||
sad o40
|
sad o40
|
||||||
jmp eoname
|
jmp eoname
|
||||||
jmp discard
|
jmp discard
|
||||||
|
|
||||||
" here with EOF in command
|
" here with EOF in command: process command?
|
||||||
eof:
|
eof:
|
||||||
sys exit " quit, for now?
|
sys exit " quit, for now?
|
||||||
|
|
||||||
" name ended (short) with whitespace or newline
|
" name ended (short) with whitespace or newline
|
||||||
" pad out last name to 8 with spaces
|
" pad out last name to 8 with spaces
|
||||||
ws:
|
ws:
|
||||||
dac char
|
dac char " save terminator
|
||||||
1: lac o40
|
1: lac o40
|
||||||
jms putc " no: copy into argv
|
jms putc " no: copy into argv
|
||||||
isz bcount " loop until full
|
isz bcount " loop until full
|
||||||
@@ -104,9 +105,10 @@ ws:
|
|||||||
|
|
||||||
" saw end of name
|
" saw end of name
|
||||||
eoname:
|
eoname:
|
||||||
|
dac char
|
||||||
lac redirect
|
lac redirect
|
||||||
sza
|
sza
|
||||||
jmp 1f " last name was a redirect file, skip increment
|
jmp 2f " last name was a redirect file, skip increment
|
||||||
|
|
||||||
lac argc " increment argc
|
lac argc " increment argc
|
||||||
tad d4
|
tad d4
|
||||||
@@ -115,19 +117,13 @@ eoname:
|
|||||||
tad d4 " advance nextarg
|
tad d4 " advance nextarg
|
||||||
dac nextarg
|
dac nextarg
|
||||||
|
|
||||||
1f:
|
2:
|
||||||
dzm redirect " clear redirect flag
|
dzm redirect " clear redirect flag
|
||||||
" TEMP output each name on a line:
|
|
||||||
lac d1; sys write; gt; 1
|
|
||||||
lac d1; sys write; 8:0; 4
|
|
||||||
lac d1; sys write; nl; 1
|
|
||||||
|
|
||||||
lac nextarg
|
lac nextarg
|
||||||
dac opt
|
dac opt
|
||||||
dac 8b " TEMP
|
|
||||||
|
|
||||||
lac char
|
lac char
|
||||||
sad o12
|
jms delim
|
||||||
jmp eol
|
jmp eol
|
||||||
|
|
||||||
-maxargs
|
-maxargs
|
||||||
@@ -135,41 +131,42 @@ eoname:
|
|||||||
sza
|
sza
|
||||||
jmp newarg
|
jmp newarg
|
||||||
|
|
||||||
" too many args, (complain?) eat rest of line
|
" too many args, (complain?). for now eat rest of line
|
||||||
4: jms getc
|
4: jms getc
|
||||||
sad o12
|
jms delim
|
||||||
skp
|
skp
|
||||||
jmp 4b
|
jmp 4b
|
||||||
|
lac d1; sys write; toomany; ltoomany
|
||||||
|
jmp newline
|
||||||
|
|
||||||
" here at end of line
|
" here at end of line
|
||||||
eol:
|
eol:
|
||||||
cla " get anything?
|
sad delimchar " save eol character
|
||||||
sad argc
|
lac argc " check for empty command line
|
||||||
jmp newline " no, go back for another
|
sna " get anything?
|
||||||
|
jmp 2f " no, go back for another
|
||||||
|
|
||||||
lac argv0 " check for built-in "chdir" command
|
" check for built-in "chdir" command
|
||||||
sad chdir
|
lac argv0
|
||||||
|
sad chdirstr
|
||||||
skp
|
skp
|
||||||
jmp forkexec
|
jmp 1f
|
||||||
lac argv0+1
|
lac argv0+1
|
||||||
sad chdir+1
|
sad chdirstr+1
|
||||||
skp
|
skp
|
||||||
jmp forkexec
|
jmp 1f
|
||||||
lac argv0+2
|
lac argv0+2
|
||||||
sad chdir+2
|
sad chdirstr+2
|
||||||
jmp changedir
|
jmp changedir
|
||||||
|
|
||||||
forkexec:
|
1:
|
||||||
" temp just exec in place
|
" comment these out to test "exec"
|
||||||
" sys fork
|
sys fork
|
||||||
" jmp parent
|
jmp parent
|
||||||
|
|
||||||
dac pid " here in child: save parent pid for smes
|
|
||||||
|
|
||||||
|
" here in child
|
||||||
lac d2; sys close " close fd 2
|
lac d2; sys close " close fd 2
|
||||||
|
sys unlink; exectemp " remove temp file
|
||||||
" XXX open executable BEFORE I/O redirection, so we can output error!!!!
|
|
||||||
sys unlink; exectemp
|
|
||||||
|
|
||||||
" try to link binary from "system" directory to "exectemp" file
|
" try to link binary from "system" directory to "exectemp" file
|
||||||
" sys link; system; argv0; exectemp
|
" sys link; system; argv0; exectemp
|
||||||
@@ -180,14 +177,9 @@ forkexec:
|
|||||||
" jmp error
|
" jmp error
|
||||||
" sys unlink; exectemp
|
" sys unlink; exectemp
|
||||||
" jmp 1f
|
" jmp 1f
|
||||||
|
"notsys: " not found in "system"
|
||||||
|
|
||||||
lac d1; sys write; star; 1
|
sys open; argv0; 0 " try cwd
|
||||||
lac d1; sys write; star; 1
|
|
||||||
lac d1; sys write; argv0; 4
|
|
||||||
lac d1; sys write; nl; 1
|
|
||||||
|
|
||||||
notsys: " not found in "system"
|
|
||||||
sys open; argv0; 0 " try cwd
|
|
||||||
spa
|
spa
|
||||||
jmp cmderr
|
jmp cmderr
|
||||||
|
|
||||||
@@ -207,68 +199,95 @@ notsys: " not found in "system"
|
|||||||
spa
|
spa
|
||||||
jmp outerror
|
jmp outerror
|
||||||
|
|
||||||
|
" here to "exec" file open on fd 2, adapted from init.s
|
||||||
" here to "exec" file open on fd 2, adapted from init.s:
|
|
||||||
exec:
|
exec:
|
||||||
law boot-1 " Get source addr
|
law boot-1 " Get source addr
|
||||||
dac 8 " set up index 8 (pre-increments)
|
dac 8 " set up index 8 (pre-increments)
|
||||||
law bootloc-1 " Copy the code at the boot label into high memory
|
law bootloc-1 " Copy "boot" code into high memory
|
||||||
dac 9 " set up index 9 (pre-increments)
|
dac 9 " set up index 9 (pre-increments)
|
||||||
1: lac 8 i
|
1: lac 8 i
|
||||||
dac 9 i
|
dac 9 i
|
||||||
isz bootcount
|
isz bootcount " can only do this once!
|
||||||
jmp 1b
|
jmp 1b
|
||||||
jmp bootloc " and then jump to the code
|
jmp bootloc " and then jump to the code
|
||||||
|
|
||||||
" copied up to bootloc in high memory (below argc)
|
" copied up to bootloc in high memory (below argc)
|
||||||
boot:
|
boot:
|
||||||
lac d2 " Load fd 2 (the opened executable)
|
lac d2 " Load fd 2 (the opened executable)
|
||||||
lmq " Save the fd into MQ
|
lmq " Save the fd into MQ
|
||||||
sys read; userbase; userlen " read executable in
|
sys read; userbase; userlen " read executable in
|
||||||
lacq " Get the fd back and close the file
|
lacq " Get the fd back and close the file
|
||||||
sys close
|
sys close
|
||||||
jmp userbase " and jump to the beginning of the executable
|
jmp userbase " and jump to the beginning of the executable
|
||||||
bootlen=.-boot " length of bootstrap
|
bootlen=.-boot " length of bootstrap
|
||||||
|
|
||||||
bootcount: -bootlen " isz loop count for bootstrap copy
|
bootcount: -bootlen " isz loop count for bootstrap copy
|
||||||
|
|
||||||
" error in child process:
|
" error in child process:
|
||||||
inerror: " error opening input redirection
|
inerror: " error opening input redirection
|
||||||
lac infilep
|
lac infilep
|
||||||
jmp error
|
jmp error
|
||||||
outerror: " error opening output redirection (stdout closed!)
|
outerror: " error opening new stdout (stdout closed!)
|
||||||
lac outfilep
|
lac outfilep
|
||||||
skp
|
skp
|
||||||
cmderr: " error opening command
|
cmderr: " error opening command
|
||||||
lac argv0p
|
lac argv0p
|
||||||
error: " here for error in child: filename pointer in AC
|
error: " error in child: filename pointer in AC
|
||||||
dac 1f " save filename to complain about
|
dac 1f " save filename to complain about
|
||||||
lac d1; sys write; qmsp; 1
|
|
||||||
lac d1; sys write; 1: 0; 4
|
lac d1; sys write; 1: 0; 4
|
||||||
lac d1; sys write; nl; 1
|
lac d1; sys write; qmnl; 1
|
||||||
lac d2; sys close
|
lac d2; sys close
|
||||||
sys exit
|
sys exit
|
||||||
|
|
||||||
" end code from init.s
|
" chdir command: executed in shell process
|
||||||
" ================
|
changedir:
|
||||||
|
" XXX check if argc == 4 (no directories) and complain??
|
||||||
|
lac argv0p
|
||||||
|
skp
|
||||||
|
1: lac 0f " increment argvp
|
||||||
|
tad d4
|
||||||
|
sad 0f
|
||||||
|
-4 " decrement argc
|
||||||
|
tad argc
|
||||||
|
dac argc
|
||||||
|
sna " done?
|
||||||
|
jmp 2f " yes: join parent code
|
||||||
|
sys chdir; 0:0
|
||||||
|
sma " error?
|
||||||
|
jmp 1b " no: look for another directory
|
||||||
|
|
||||||
|
" chdir call failed
|
||||||
|
lac 0b
|
||||||
|
dac 0f
|
||||||
|
lac d1; sys write; 0:0; 4
|
||||||
|
lac d1; sys write; qmnl; 1
|
||||||
|
jmp 2f " join parent code
|
||||||
|
|
||||||
" here in parent, child pid in AC
|
" here in parent, child pid in AC
|
||||||
parent:
|
parent:
|
||||||
" sys smes " hangs until child exits
|
" https://www.bell-labs.com/usr/dmr/www/hist.html
|
||||||
jmp newline
|
" The message facility was used as follows: the parent shell, after
|
||||||
|
" creating a process to execute a command, sent a message to the new
|
||||||
" chdir command:
|
" process by smes; when the command terminated (assuming it did not
|
||||||
changedir:
|
" try to read any messages) the shell's blocked smes call returned an
|
||||||
" XXX check argc > 1!!!
|
" error indication that the target process did not exist. Thus the
|
||||||
lac d1; sys write; gt; 1
|
" shell's smes became, in effect, the equivalent of wait.
|
||||||
lac d1; sys write; gt; 1
|
dac pid
|
||||||
lac d1; sys write; gt; 1
|
lac delimchar
|
||||||
lac d1; sys write; argv0+4; 4
|
sad o46 " ampersand?
|
||||||
" XXX loop for multiple components!!!
|
jmp newcom " yes: go back without wait
|
||||||
jmp newline
|
lac pid
|
||||||
|
sys smes " hang until child exits
|
||||||
|
2: lac delimchar
|
||||||
|
sad o73 " semi?
|
||||||
|
jmp newcom " yes: look for another command w/o prompt
|
||||||
|
jmp newline " no: output prompt
|
||||||
|
|
||||||
" ================
|
" ================
|
||||||
" subroutines
|
" subroutines
|
||||||
|
|
||||||
|
" eat spaces
|
||||||
|
" v1 routine name:
|
||||||
blank: 0
|
blank: 0
|
||||||
1: jms getc
|
1: jms getc
|
||||||
sad o40
|
sad o40
|
||||||
@@ -276,25 +295,29 @@ blank: 0
|
|||||||
jmp blank i
|
jmp blank i
|
||||||
|
|
||||||
" give skip return if AC *NOT* a command delimiter
|
" give skip return if AC *NOT* a command delimiter
|
||||||
|
" v1 routine name:
|
||||||
delim: 0
|
delim: 0
|
||||||
sad o12
|
sad o12 " newline
|
||||||
jmp delim i
|
jmp delim i
|
||||||
isz delim
|
sad o46 " ampersand
|
||||||
|
jmp delim i
|
||||||
|
sad o73 " semi
|
||||||
|
jmp delim i
|
||||||
|
isz delim " ran the gauntlet: skip home
|
||||||
jmp delim i
|
jmp delim i
|
||||||
|
|
||||||
" ****************************************************************
|
|
||||||
" from cat.s
|
" from cat.s
|
||||||
getc: 0
|
getc: 0
|
||||||
lac ipt " Load the pointer to the next word in the buffer
|
lac ipt " Load pointer to next word in the buffer
|
||||||
sad eipt
|
sad eipt
|
||||||
jmp 1f " We've reached the end of the buffer, so read more
|
jmp 1f " end of the buffer, so read more
|
||||||
dac 2f " Save the pointer
|
dac 2f " Save the pointer
|
||||||
add o400000 " Flip the msb and save into ipt
|
add o400000 " flip MSB, increment pointer on overflow
|
||||||
dac ipt
|
dac ipt
|
||||||
ral " Move the msb into the link register
|
ral " Move the msb into the link register
|
||||||
lac 2f i " Load the word from the buffer
|
lac 2f i " Load the word from the buffer
|
||||||
szl " Skip if this is the second character in the word
|
szl " Skip if second character in word
|
||||||
lrss 9 " It's the first char, shift down the top character
|
lrss 9 " first char: shift down the top character
|
||||||
and o177 " Keep the lowest 7 bits
|
and o177 " Keep the lowest 7 bits
|
||||||
sna
|
sna
|
||||||
jmp getc+1 " Skip a NUL characters and read another one
|
jmp getc+1 " Skip a NUL characters and read another one
|
||||||
@@ -341,37 +364,38 @@ eipt: 0 " Pointer to end of data read in input buffer
|
|||||||
iipt: ibuf
|
iipt: ibuf
|
||||||
ibuf: .=.+64
|
ibuf: .=.+64
|
||||||
|
|
||||||
|
|
||||||
" end from cat.s
|
|
||||||
" ****************************************************************
|
|
||||||
" literals
|
" literals
|
||||||
d1: 1
|
d1: 1
|
||||||
d2: 2
|
d2: 2
|
||||||
o4:d4: 4
|
o4:d4: 4
|
||||||
o12:nl: 012 " newline
|
o12: 012 " newline
|
||||||
o17: 017
|
o17: 017
|
||||||
o40:sp: 040 " space
|
o40: 040 " space
|
||||||
o74:lt: 074
|
o46: 046 " ampersand
|
||||||
o76:gt: 076
|
o73: 046 " semi
|
||||||
o177: 0177 " ASCII mask
|
o74:lt: 074 " <
|
||||||
o400000: 0400000 " Msb toggle bit
|
o76:gt: 076 " >
|
||||||
|
o177: 0177 " 7-bit (ASCII) mask
|
||||||
|
o400000: 0400000 " MSB
|
||||||
|
|
||||||
hash: <#> " superuser prompt
|
hash: <#> " superuser prompt
|
||||||
qmsp: <? > " " question mark, space
|
qmnl: <? 012 " question mark, newline
|
||||||
" (traditional DDT error label was "dt"
|
|
||||||
" for "dink, tab")
|
|
||||||
system:
|
system:
|
||||||
<sy>;<st>;<em>; 040040
|
<sy>;<st>;<em>; 040040
|
||||||
|
|
||||||
exectemp:
|
exectemp:
|
||||||
<ex>;<ec>;<te><mp> " temporary link for file being exec'ed
|
<ex>;<ec>;<te>;<mp> " temporary link for file being exec'ed
|
||||||
|
|
||||||
chdir:
|
chdirstr:
|
||||||
<ch>;<di>;<r 040
|
<ch>;<di>;<r 040
|
||||||
|
|
||||||
" TEMP FOR DEBUG:
|
" TEMP FOR DEBUG:
|
||||||
star: <*> "
|
star: <*> "
|
||||||
|
|
||||||
|
toomany: <to>;<o> ;<ma>;<ny>;< a>;<rg>;<s 012
|
||||||
|
ltoomany=.-toomany
|
||||||
|
|
||||||
" ################ variables
|
" ################ variables
|
||||||
|
|
||||||
prompt: <@> " v1 prompt
|
prompt: <@> " v1 prompt
|
||||||
@@ -379,6 +403,7 @@ pid: 0 " "other" pid
|
|||||||
char: 0 " white space char
|
char: 0 " white space char
|
||||||
redirect: 0 " last file was a redirect (lt or gt)
|
redirect: 0 " last file was a redirect (lt or gt)
|
||||||
bcount: 0 " byte counter for current filename
|
bcount: 0 " byte counter for current filename
|
||||||
|
delimchar: 0 " character that terminated line
|
||||||
|
|
||||||
iopt:argv0p: argv0 " initial value for nextarg, opt
|
iopt:argv0p: argv0 " initial value for nextarg, opt
|
||||||
nextarg: 0 " next slot in argv to fill
|
nextarg: 0 " next slot in argv to fill
|
||||||
|
|||||||
@@ -53,6 +53,13 @@ GetOptions(
|
|||||||
|
|
||||||
usage() if ( @ARGV < 1 );
|
usage() if ( @ARGV < 1 );
|
||||||
|
|
||||||
|
# http://minnie.tuhs.org/cgi-bin/utree.pl?file=V3/man/manx/as.1
|
||||||
|
# ".." is the relocation constant and is added to each relocatable
|
||||||
|
# reference. On a PDP-11 with relocation hardware, its value is 0; on
|
||||||
|
# most systems without protection, its value is 40000(8).
|
||||||
|
|
||||||
|
# PLB: "relocatable" values are flagged with $RELATIVE
|
||||||
|
|
||||||
# start with the location counter at zero
|
# start with the location counter at zero
|
||||||
# predefine syscall and opcodes as variables
|
# predefine syscall and opcodes as variables
|
||||||
%Var = (
|
%Var = (
|
||||||
|
|||||||
Reference in New Issue
Block a user