mirror of
https://github.com/PDP-10/its.git
synced 2026-01-24 03:18:05 +00:00
2045 lines
36 KiB
Plaintext
Executable File
2045 lines
36 KiB
Plaintext
Executable File
; -*-MIDAS-*-
|
||
TITLE DSKUSE -- DSK INFO -- PDL 2/19/76
|
||
|
||
;9/6/79 Modified for new TUT format (ITS 1154)
|
||
|
||
; note to the perplexed: The value of the symbol
|
||
; MAXUSR (currently 512.) controls how many users DSKUSE can handle.
|
||
; since this is the maximum number of directories ITS can have in the
|
||
; current implementation, this should be enough.
|
||
|
||
.MLLIT=1
|
||
|
||
; ====================================================================
|
||
; accumulator definitions
|
||
; ====================================================================
|
||
|
||
A=1
|
||
B=2
|
||
C=3
|
||
D=4
|
||
E=5
|
||
F=6
|
||
G=7
|
||
H=10
|
||
I=11
|
||
J=12
|
||
K=13
|
||
L=14
|
||
M=15
|
||
N=16
|
||
ARGP=16
|
||
P=17
|
||
|
||
TYIC==1 ; channels
|
||
TYOC==2
|
||
CH==3
|
||
MCH==4
|
||
TCMD==5 ; command output channel
|
||
|
||
; disk system variables
|
||
|
||
.INSRT SYSTEM;FSDEFS >
|
||
|
||
%USRBLK==8 ; size of single user info block
|
||
|
||
%USER==0 ; offsets of data
|
||
%FILES==1
|
||
%LINKS==2
|
||
%BLCKS==3
|
||
%QUOTA==4
|
||
%ALLOC==5
|
||
%PACKN==6
|
||
%BLKAV==7
|
||
|
||
; command macro
|
||
|
||
DEFINE COM DIS,NMS
|
||
IRP NM,,[NMS]
|
||
SIXBIT \!NM!\
|
||
PUSHJ P,DIS
|
||
TERMIN
|
||
TERMIN
|
||
|
||
; fix and float macros
|
||
|
||
DEFINE FLOAT AX,AY
|
||
TLC AX,232000+1000*AY
|
||
FADR AX,AX
|
||
TERMIN
|
||
|
||
DEFINE FIX AX,AY
|
||
MULI AX,400
|
||
TSC AX,AX
|
||
ASH AX+1,AY-243(AX)
|
||
TERMIN
|
||
|
||
; ====================================================================
|
||
; :dskuse ?
|
||
; ====================================================================
|
||
|
||
CINFO: ASCIZ \
|
||
DSKUSE is usually driven by a command from its JCL line, as follows:
|
||
|
||
:DSKUSE user statistics on the user directory given, or the MSNAME
|
||
directory if no argument.
|
||
:DSKUSE > user print message if MSNAME user (or user given explicitly)
|
||
is over quota, else nothing.
|
||
|
||
:DSKUSE @ file statistics on all users output to TPL:, or to file
|
||
if given.
|
||
:DSKUSE & file output two tables, sorted on user and blocks, to TPL:
|
||
or to file if given.
|
||
|
||
:DSKUSE # general statistics on disk system (takes time).
|
||
:DSKUSE $ same as previous, only less detailed (faster, too).
|
||
|
||
:DSKUSE % user print % of directory space used by user.
|
||
|
||
:DSKUSE * statistics on all users, in tabular form.
|
||
this command is special in that it leaves you in DSKUSE.
|
||
you may type the number or name of a column to sort by
|
||
that column and then reprint the table (0 or USER, 1 or
|
||
FILES, etc.). in this mode the @ command, with a file
|
||
name optionally following it, causes subsequent sorts
|
||
to go to the file. the commands #, %, and > are not
|
||
available. The dual sort (& or BOTH) is, however.
|
||
|
||
For more details see .INFO.;DSKUSE INFO.\
|
||
|
||
INFO: OASCR CINFO
|
||
JRST KILL
|
||
|
||
; ====================================================================
|
||
; DSKUSE
|
||
; ====================================================================
|
||
|
||
START: MOVE P,[-100,,PDL] ; set up pdl
|
||
|
||
; here to open ttys
|
||
.OPEN TYIC,[SIXBIT / TTYFOOBARBLECH /]
|
||
.VALUE [ASCIZ /:CANT OPEN TTY/]
|
||
.OPEN TYOC,[SIXBIT / !TTYXXXXXXYYYYYY/]
|
||
.VALUE [ASCIZ !:CANT OPEN TTY!]
|
||
.OPEN TCMD,[SIXBIT / 1TTYXXXXXXYYYYYY/]
|
||
.VALUE [ASCIZ !:CANT OPEN TTY!]
|
||
|
||
; set up TTY interrupt
|
||
.CALL [SETZ
|
||
'TTYGET
|
||
1000,,TYIC
|
||
2000,,A
|
||
402000,,B]
|
||
.VALUE [ASCIZ /:CANT GET CONSOLE TYPE/]
|
||
; make only ^G and ^S interrupt
|
||
MOVE 0,[SIXBIT / !!!!!/]
|
||
ANDCAM 0,A
|
||
MOVE 0,[SIXBIT / !!!!!/]
|
||
ANDCAM 0,B
|
||
.CALL [SETZ
|
||
'TTYSET
|
||
1000,,TYIC
|
||
A
|
||
400000,,B]
|
||
.VALUE [ASCIZ /:CANT SET CONSOLE TYPE/]
|
||
; enable interrupt
|
||
MOVEI A,1 ; tty int
|
||
SETZ B,
|
||
.SETM2 A,
|
||
|
||
; get msname of user
|
||
.SUSET [.RSNAM,,RSYSNM]
|
||
MOVE RSYSNM
|
||
MOVEM USRNAM
|
||
; get command from superior
|
||
.SUSET [.ROPTIO,,A]
|
||
TLNN A,40000 ; OPTCMD
|
||
JRST HUSER
|
||
.BREAK 12,[5,,COMMND]
|
||
SKIPN COMMND
|
||
JRST HUSER ; no argument
|
||
|
||
; got arg, so parse it
|
||
MOVE [440700,,COMMND]
|
||
MOVEM COMPTR
|
||
PUSHJ P,GETSYL ; get command, if any
|
||
JUMPE B,HUSER
|
||
|
||
; dispatch
|
||
MOVE A,SWPTR
|
||
JCLOOP: CAMN B,(A)
|
||
JRST @1(A)
|
||
AOS A
|
||
AOBJN A,JCLOOP
|
||
MOVEM B,USRNAM
|
||
JRST OUSER ; assume funny user
|
||
|
||
; ====================================================================
|
||
; jcl line command table
|
||
; ====================================================================
|
||
|
||
SWTABL: COM AUSER,[&] ; two column, user and blocks sorted
|
||
COM AUSER1,[@] ; one column, user, to tpl
|
||
COM AUSER2,[*] ; one column, no tpl
|
||
COM DSKDAT,[$] ; quick statistics
|
||
COM QUSER,[#] ; detailed statistics
|
||
COM UFULL,[%] ; percent of dir used
|
||
COM UFULLB,[%%] ; dir bloated?
|
||
COM UOVER,[>] ; quota check
|
||
COM INFO,[?] ; info
|
||
SWPTR: -<<.-SWTABL>/2>,,SWTABL
|
||
|
||
; ====================================================================
|
||
; :DSKUSE %
|
||
; ====================================================================
|
||
|
||
UFULLB: SETOM UFULLF'
|
||
UFULL: PUSHJ P,GETSYL
|
||
SKIPE B
|
||
MOVEM B,USRNAM
|
||
.SUSET [.SSNAM,,USRNAM]
|
||
; read ufd in
|
||
.OPEN CH,UDIR
|
||
JRST NOUFD
|
||
MOVE A,[-2000,,FDIR]
|
||
.IOT CH,A
|
||
.CLOSE CH,
|
||
PUSHJ P,UFULL0
|
||
JRST KILL
|
||
|
||
UFULL0: MOVE D,UDESCP+FDIR
|
||
MOVEI C,UDDESC+FDIR ; ; D/ desc count
|
||
HRLI C,440600 ; "BYTE PTR"
|
||
SETZ B, ; "COUNT"
|
||
NEXTA: SETZ A,
|
||
NEXTB: SOJL D,FEND
|
||
ILDB C
|
||
JUMPE NBYTE ; "ZERO BYTE?"
|
||
SETOM A ; "NON-ZERO BYTE"
|
||
JRST NEXTB ; "LOOP"
|
||
NBYTE: JUMPN A,NEXTA ; "ZERO, WAS LAST ZERO?"
|
||
SETZM A
|
||
AOJA B,NEXTB ; "AOS NULL COUNT"
|
||
FEND: MOVE C,UDESCP+FDIR
|
||
SUB C,B
|
||
IDIVI C,6 ; "NUMBER OF WORDS"
|
||
|
||
ADDI C,2000
|
||
SUB C,UDNAMP+FDIR
|
||
FLOAT C
|
||
|
||
MOVEI B,2000-UDDESC
|
||
FLOAT B
|
||
FDVR B,[100.0]
|
||
FDVR C,B
|
||
|
||
SKIPN UFULLF
|
||
JRST UFULLP
|
||
CAMGE C,[97.0]
|
||
POPJ P,
|
||
UFULLP: OASC [ASCIZ /Directory /]
|
||
OSIX USRNAM
|
||
OASC [ASCIZ / is /]
|
||
JUMPE C,UEMPTY
|
||
OFLOAT C
|
||
OASCR [ASCIZ /% full./]
|
||
POPJ P,
|
||
|
||
UEMPTY: OASCR [ASCIZ /empty./]
|
||
POPJ P,
|
||
|
||
; ====================================================================
|
||
; :DSKUSE >
|
||
; ====================================================================
|
||
|
||
UOVER: PUSHJ P,GETSYL
|
||
SKIPE B
|
||
MOVEM B,USRNAM
|
||
.SUSET [.SSNAM,,USRNAM]
|
||
PUSHJ P,USRDSK
|
||
JRST KILL
|
||
MOVE B,UBLCKS
|
||
CAMG B,UQUOTA
|
||
JRST KILL
|
||
SUBM B,UQUOTA
|
||
OASCR [0]
|
||
OSIX USRNAM
|
||
OASC [ASCIZ / OVER QUOTA BY /]
|
||
ODEC UQUOTA
|
||
OASCR [ASCIZ / BLOCKS/]
|
||
JRST KILL
|
||
|
||
; ====================================================================
|
||
; :DSKUSE #
|
||
; ====================================================================
|
||
|
||
QUSER: PUSHJ P,DSKAV
|
||
PUSHJ P,GATHER
|
||
PUSHJ P,DATOUT
|
||
OASCR [0]
|
||
PUSHJ P,QSKOUT
|
||
JRST KILL
|
||
|
||
; ====================================================================
|
||
; :DSKUSE %
|
||
; ====================================================================
|
||
|
||
; here for general data
|
||
DSKDAT: PUSHJ P,DSKAV ; get system data
|
||
PUSHJ P,DATOUT ; print system data
|
||
JRST KILL ; exit
|
||
|
||
; ====================================================================
|
||
; :DSKUSE
|
||
; ====================================================================
|
||
|
||
; here for just doing this user
|
||
HUSER: .SUSET [.RSNAM,,USRNAM]
|
||
JRST EUSER
|
||
|
||
; ====================================================================
|
||
; :DSKUSE <user>
|
||
; ====================================================================
|
||
|
||
; here for specified user
|
||
OUSER: SKIPE USRNAM
|
||
.SUSET [.SSNAM,,USRNAM]
|
||
|
||
; common area for single user dskuse
|
||
EUSER: OASCR [0]
|
||
PUSHJ P,DSKAV ; get data on system as whole
|
||
PUSHJ P,USRDSK ; get data on single user
|
||
JRST NOUFD
|
||
|
||
; print data for single user
|
||
PUSHJ P,UFULL0
|
||
;OASC [ASCIZ /User /]
|
||
;OSIX USRNAM
|
||
;OASCR [0]
|
||
OASC [ASCIZ /Files /]
|
||
ODECR UFILES
|
||
OASC [ASCIZ /Links /]
|
||
ODECR ULINKS
|
||
OASC [ASCIZ /Blocks /]
|
||
ODEC UBLCKS
|
||
SKIPN UPACKN
|
||
JRST EUQOTA
|
||
OASCR [0]
|
||
OASC [ASCIZ/Allocated to pack /]
|
||
ODEC UPACKN
|
||
;Attempt to extract pack name out of the system
|
||
MOVE A,UPACKN
|
||
MOVE B,NQS
|
||
SUBI B,1
|
||
CAME A,QPKID(B)
|
||
SOJGE B,.-1
|
||
JUMPL B,EUQOTA
|
||
SKIPE A,TRESRV(B)
|
||
CAMN A,[-1]
|
||
JRST EUQOTA
|
||
OASC [ASCIZ/ (/]
|
||
OSIX A
|
||
OASC [ASCIZ/:)/]
|
||
EUQOTA: SKIPG A,UQUOTA
|
||
JRST EUSBLK
|
||
CAMGE A,UBLCKS
|
||
OASCI "*
|
||
EUSBLK: OASCR [0]
|
||
SKIPG UALLOC
|
||
JRST EUSERQ
|
||
OASC [ASCIZ \Allocation \]
|
||
ODECR UALLOC
|
||
EUSERQ: MOVE A,UALLOC
|
||
CAMN A,UQUOTA
|
||
JRST EUSYST
|
||
OASC [ASCIZ \Quota \]
|
||
ODECR UQUOTA
|
||
|
||
; print data for system as a whole
|
||
EUSYST: OASC [ASCIZ \Free Blocks \]
|
||
SKIPG FREEBL
|
||
JRST EUSYS1
|
||
; here if there are allocations
|
||
OASCR [0]
|
||
OASC [ASCIZ \ Unallocated \]
|
||
ODECR FRUNAL
|
||
OASC [ASCIZ \ Allocated \]
|
||
ODEC FREEBL
|
||
EUSYS2: OASC [ASCIZ \ of \]
|
||
ODECR ALLBL
|
||
OASC [ASCIZ \Average User \]
|
||
ODECR AVER
|
||
JRST KILL ; exit
|
||
; here if there are no allocations
|
||
EUSYS1: ODEC FRUNAL
|
||
JRST EUSYS2
|
||
|
||
; ====================================================================
|
||
; :DSKUSE &
|
||
; ====================================================================
|
||
|
||
AUSER: SETOM BOTH ; set & flag
|
||
|
||
; ====================================================================
|
||
; :DSKUSE @
|
||
; ====================================================================
|
||
|
||
; here to output table to disk
|
||
AUSER1: PUSHJ P,SCNAME
|
||
PUSHJ P,DSKOUT ; open disk channel
|
||
SETOM JCLFLG
|
||
|
||
; ====================================================================
|
||
; :DSKUSE *
|
||
; ====================================================================
|
||
|
||
; here to output table to tty after finishing
|
||
|
||
AUSER2: SETZB G,H
|
||
SETZ I,
|
||
OASCR [0]
|
||
|
||
; get data on date, time, and system name
|
||
|
||
; what system are we on?
|
||
.CALL RDSYST
|
||
JFCL
|
||
; time
|
||
.RTIME A,
|
||
MOVEM A,TIME
|
||
; date
|
||
.RDATE A,
|
||
ROT A,12.
|
||
MOVEM A,DATE
|
||
|
||
; optional sort number 0 => 5
|
||
PUSHJ P,GETSYL
|
||
LDB A,[360600,,B]
|
||
SUBI A,20
|
||
CAIL A,0
|
||
CAILE A,5 ; 6 columns
|
||
SETZ A,
|
||
SKIPE A
|
||
MOVEM A,SORTX ; sort on what entry in vector?
|
||
HRRM A,SORTX
|
||
|
||
; enter loop here to get users and status them one after another
|
||
; out of mfd
|
||
|
||
PUSHJ P,DSKAV
|
||
PUSHJ P,GETMFD
|
||
PUSHJ P,GATHER ; here to frob all ufd's
|
||
|
||
HRRI N,USERS ; save aobjn to users
|
||
MOVEM N,CPTR
|
||
|
||
; calculate blocks/file
|
||
MOVE A,TBL
|
||
MOVE B,TFL
|
||
FLOAT A,
|
||
FLOAT B,
|
||
FDVR A,B
|
||
MOVEM A,TAV
|
||
JRST ENDST1
|
||
|
||
; call block for .call /sstatu/
|
||
|
||
RDSYST: SETZ
|
||
SIXBIT /SSTATU/
|
||
2000,,0
|
||
2000,,0
|
||
2000,,0
|
||
2000,,0
|
||
2000,,0
|
||
SETZM SYSNAM
|
||
; * print *
|
||
|
||
ENDST1: SKIPL BOTH
|
||
JRST ONESRT
|
||
|
||
; * here for & dskuse (0 & 3 sort at once) *
|
||
|
||
; do 3 sort (blocks)
|
||
MOVEI A,3
|
||
MOVE M,CPTR
|
||
PUSHJ P,VSORT
|
||
; move results into second data vector
|
||
MOVE M,CPTR
|
||
HRRI M,FDIR
|
||
MOVEM M,CPTR1
|
||
MOVE A,[USERS,,FDIR]
|
||
BLT A,FDIR+MAXUSR-1
|
||
|
||
; do 0 sort
|
||
MOVSI A,-1
|
||
MOVE M,CPTR
|
||
PUSHJ P,VSORT
|
||
JRST PRTSRT ; print results
|
||
|
||
; * do single sort *
|
||
|
||
ONESRT: MOVE A,SORTX ; sort key
|
||
MOVE M,CPTR ; cptr
|
||
PUSHJ P,VSORT ; do it
|
||
; here to print sort
|
||
PRTSRT: OASCI ^L ; form feed
|
||
OASCR [0]
|
||
|
||
; herald message
|
||
OSIX SYSNAM
|
||
OASC [ASCIZ \ DISK USAGE by \]
|
||
OSIX RSYSNM
|
||
OASC [ASCIZ \ at \]
|
||
OTIME TIME
|
||
OASC [ASCIZ \ on \]
|
||
ODATE DATE
|
||
OASCR [0]
|
||
OASCR [0]
|
||
|
||
; general system data
|
||
PUSHJ P,DATOUT
|
||
OASCR [0]
|
||
SKIPN BOTH
|
||
JRST COLHDR
|
||
PUSHJ P,QSKOUT
|
||
OASCR [0]
|
||
|
||
; column header(s)
|
||
COLHDR: OASCR [0]
|
||
PUSHJ P,TYPHDR
|
||
SKIPN BOTH
|
||
JRST ONEHDR
|
||
|
||
; here to type extra header for & mode
|
||
OASC [ASCIZ \ \]
|
||
PUSHJ P,TYPHDR
|
||
OASCR [0]
|
||
|
||
; underline appropriate column headers
|
||
OASC [ASCIZ \---- \]
|
||
SKIPG TQUO
|
||
JRST COLHD1
|
||
OASCI ^I
|
||
COLHD1: SKIPG TALLO
|
||
JRST COLHD2
|
||
OASCI ^I
|
||
COLHD2: OASCR [ASCIZ \ ------\]
|
||
JRST TYPSTT ; start normal typeout
|
||
|
||
; here to underline normal header
|
||
ONEHDR: OASCR [0]
|
||
HRRZ B,SORTX
|
||
XCT PTABS(B) ; appropriate tabs
|
||
OASCR [0]
|
||
|
||
; here to start typing user stats
|
||
TYPSTT: OASCR [0]
|
||
MOVE D,CPTR
|
||
MOVE G,CPTR1
|
||
; loop
|
||
TYPNXT: MOVE A,(D)
|
||
PUSHJ P,TYPOUT
|
||
SKIPN BOTH
|
||
JRST TYPEND
|
||
OASC [ASCIZ \ \]
|
||
MOVE A,(G)
|
||
PUSHJ P,TYPOUT
|
||
TYPEND: OASCR [0]
|
||
ADD G,[1,,1]
|
||
AOBJN D,TYPNXT
|
||
|
||
; done, type totals
|
||
OASCR [0]
|
||
PUSHJ P,TYPTOT
|
||
SKIPN BOTH
|
||
JRST TYPGET
|
||
|
||
; type extra total, for second list in & dskuse
|
||
OASC [ASCIZ \ \]
|
||
PUSHJ P,TYPTOT
|
||
|
||
; form feed if in & mode
|
||
SKIPE BOTH
|
||
OASCI ^L
|
||
|
||
; prepare to get a command
|
||
TYPGET: SETZM BOTH
|
||
|
||
; here to get a command typed from tty, after we have performed
|
||
; the single command that could be given when dskuse was invoked.
|
||
TYPCOM: SKIPE JCLFLG'
|
||
JRST KILL
|
||
.IOT TCMD,["*]
|
||
MOVE N,M
|
||
PUSHJ P,READ
|
||
PUSHJ P,GETSYL
|
||
|
||
MOVE A,TYPPTR
|
||
TYPLUP: CAMN B,(A)
|
||
JRST @1(A)
|
||
AOS A
|
||
AOBJN A,TYPLUP
|
||
BADCOM: .IOT TCMD,["?]
|
||
.IOT TCMD,["?]
|
||
.IOT TCMD,[^M]
|
||
.IOT TCMD,[^J]
|
||
JRST TYPCOM
|
||
|
||
TYPTAB: COM KILL,[Q,QUIT,KILL]
|
||
COM DSKOPN,[@]
|
||
COM DSKOP1,[&]
|
||
COM SRTUSR,[0,U,USER]
|
||
COM SRTFIL,[1,F,FILE,FILES]
|
||
COM SRTLNK,[2,L,LINK,LINKS]
|
||
COM SRTBLK,[3,B,BLK,BLOCK,BLOCKS]
|
||
COM SRTQUO,[4,Q,QUO,QUOTA,QUOTAS]
|
||
COM SRTALL,[5,A,ALL,ALLOC,ALLOCA]
|
||
COM SRTPCK,[6,P,PACK]
|
||
COM SRTAVG,[7,R,RATIO,B/F,BF,AVG]
|
||
TYPPTR: -<<.-TYPTAB>/2>,,TYPTAB
|
||
|
||
; ====================================================================
|
||
; sort commands
|
||
; ====================================================================
|
||
|
||
SRTUSR: MOVEI A,0
|
||
JRST SORTIT
|
||
SRTFIL: MOVEI A,1
|
||
JRST SORTIT
|
||
SRTLNK: MOVEI A,2
|
||
JRST SORTIT
|
||
SRTBLK: MOVEI A,3
|
||
JRST SORTIT
|
||
SRTQUO: MOVEI A,4
|
||
JRST SORTIT
|
||
SRTALL: MOVEI A,5
|
||
JRST SORTIT
|
||
SRTPCK: MOVEI A,6
|
||
JRST SORTIT
|
||
SRTAVG: MOVEI A,7
|
||
|
||
; if name column, sort "backwards"
|
||
SORTIT: SKIPN A
|
||
HRLI A,-1 ; sort "frontwards"
|
||
MOVEM A,SORTX ; set up sort key
|
||
JRST ENDST1
|
||
|
||
; output a double sort
|
||
DSKOP1: SETOM BOTH
|
||
JRST ENDST1
|
||
|
||
; ====================================================================
|
||
; output rest of sorts to disk
|
||
; ====================================================================
|
||
|
||
DSKOPN: PUSHJ P,SCNAME ; cons up output file spec
|
||
PUSHJ P,DSKOUT ; open it
|
||
JRST TYPCOM ; loop
|
||
|
||
; here to reopen "TTY" channel to "DSK"
|
||
DSKOUT: .SUSET [.SSNAM,,RSYSNM]
|
||
MOVEI '!
|
||
HRLM OUTPUT
|
||
.OPEN TYOC,OUTPUT
|
||
.VALUE [ASCIZ !:CANT OPEN OUTPUT FILE!]
|
||
POPJ P,
|
||
|
||
; here to exit by killing job and not typing anything
|
||
EXIT: .VALUE [ASCIZ /:KILL
|
||
|
||
/]
|
||
|
||
KILL: .BREAK 16,140000
|
||
|
||
|
||
HEADER: ASCIZ \USER Files Links Blocks\
|
||
HEADE1: ASCIZ \ Quota\
|
||
HEADE2: ASCIZ \ Alloc\
|
||
HEADE3: ASCIZ \ Pack\
|
||
HEADE4: ASCIZ \ B/F\
|
||
|
||
TYPHDR: OASC HEADER
|
||
SKIPE TQUO
|
||
OASC HEADE1
|
||
SKIPE TALLO
|
||
OASC HEADE2
|
||
OASC HEADE3
|
||
OASC HEADE4
|
||
POPJ P,
|
||
|
||
PTABS: OASC [ASCIZ /----/]
|
||
OASC [ASCIZ / -----/]
|
||
OASC [ASCIZ / -----/]
|
||
OASC [ASCIZ / ------/]
|
||
OASC [ASCIZ / -----/]
|
||
OASC [ASCIZ / -----/]
|
||
OASC [ASCIZ / ----/]
|
||
OASC [ASCIZ / ---/]
|
||
|
||
; * type total line *
|
||
|
||
TYPTOT: OASC [ASCIZ \Total \]
|
||
OJUST 3,TFL
|
||
OASCI ^I
|
||
OJUST 3,TLK
|
||
OASCI ^I
|
||
OJUST 4,TBL
|
||
OASCI ^I
|
||
SKIPG TQUO
|
||
JRST TYPTO1
|
||
OJUST 4,TQUO
|
||
OASCI ^I
|
||
TYPTO1: SKIPG TALLO
|
||
JRST TYPTO2
|
||
OJUST 4,TALLO
|
||
OASCI ^I
|
||
OASCI ^I
|
||
TYPTO2: OFLOAT TAV
|
||
POPJ P,
|
||
|
||
; * output general data *
|
||
|
||
DATOUT: OASC [ASCIZ \Total number of users is \]
|
||
ODEC TUS
|
||
SKIPG TQUO
|
||
JRST DATUAL
|
||
OASC [ASCIZ \, \]
|
||
ODEC TUQUOT
|
||
OASC [ASCIZ \ with quotas\]
|
||
|
||
DATUAL: SKIPG TALLO
|
||
JRST DATUSR
|
||
OASC [ASCIZ \, \]
|
||
ODEC TUALLO
|
||
OASC [ASCIZ \ with allocations\]
|
||
DATUSR: OASCR [0]
|
||
|
||
SKIPG TQUO
|
||
JRST DATAVG
|
||
OASC [ASCIZ \Over quota: \]
|
||
ODEC TPIGS
|
||
OASC [ASCIZ \ users, \]
|
||
ODEC TFAT
|
||
OASC [ASCIZ \ blocks, average excess \]
|
||
ODEC TBACON
|
||
OASC [ASCIZ \ blocks each\]
|
||
OASCR [0]
|
||
|
||
DATAVG: OASC [ASCIZ \Average blocks per user \]
|
||
ODEC AVER
|
||
|
||
SKIPG TQUO
|
||
JRST DATALO
|
||
OASC [ASCIZ \, per quota'ed user \]
|
||
ODEC TAQUOT
|
||
|
||
DATALO: SKIPG TALLO
|
||
JRST DATFRE
|
||
OASC [ASCIZ \, per allocated user \]
|
||
ODEC TAALLO
|
||
|
||
DATFRE: OASCR [0]
|
||
OASC [ASCIZ \Free disk blocks: \]
|
||
ODEC FRUNAL
|
||
SKIPG TALLO
|
||
JRST DATOUX
|
||
OASC [ASCIZ \ unallocated, \]
|
||
ODEC FREEBL
|
||
OASC [ASCIZ \ allocated\]
|
||
DATOUX: OASCR [0]
|
||
OASC [ASCIZ \Disk system contains \]
|
||
ODEC NQS
|
||
OASC [ASCIZ \ disks\]
|
||
MOVE A,NQS
|
||
CAMN A,NQSONL
|
||
JRST DATOUY
|
||
OASC [ASCIZ \ (\]
|
||
ODEC NQSONL
|
||
OASC [ASCIZ \ on-line)\]
|
||
DATOUY: OASC [ASCIZ \, \]
|
||
ODEC ALLBL
|
||
OASCR [ASCIZ \ blocks\]
|
||
OASC [ASCIZ \Free swapping blocks: \]
|
||
ODEC FREESW
|
||
OASC [ASCIZ \ out of \]
|
||
ODECR SWAPAL
|
||
|
||
OASC [ASCIZ \Unused UFD slots: \]
|
||
MOVE A,NUDSL
|
||
SUB A,TUS
|
||
SETZ B,
|
||
BLT B,
|
||
SKIPE B ;If this is a KL10 or a KS10, it has a
|
||
SUBI A,2 ; front-end file system in blocks 0,1
|
||
ODEC A
|
||
OASC [ASCIZ \ of \]
|
||
MOVE A,NUDSL
|
||
SKIPE B
|
||
SUBI A,2
|
||
ODECR A
|
||
|
||
POPJ P,
|
||
|
||
; here to output tables of disk crufties
|
||
QSKOUT: OASC [ASCIZ \Drive \]
|
||
SETZ K,
|
||
QSKTOP: CAML K,NQS
|
||
JRST QSKEND
|
||
OASC [ASCIZ \DK\]
|
||
ODEC K
|
||
OASC [ASCIZ \: \]
|
||
AOJA K,QSKTOP
|
||
QSKEND: OASCR [0]
|
||
OASCR [0]
|
||
OASC [ASCIZ \Pack # \]
|
||
MOVEI B,QPKID
|
||
PUSHJ P,QTABL1
|
||
OASC [ASCIZ \Disk size \]
|
||
MOVEI B,TLASTB
|
||
PUSHJ P,QTABL1
|
||
OASCR [0]
|
||
|
||
OASC [ASCIZ \Available \]
|
||
MOVEI B,TSIZES
|
||
PUSHJ P,QTABL1
|
||
|
||
; only print alloc if there is some
|
||
SKIPG TALLO
|
||
JRST QFREEP
|
||
OASC [ASCIZ \Allocated \]
|
||
MOVEI B,PACK
|
||
PUSHJ P,QTABL1
|
||
|
||
QFREEP: OASC [ASCIZ \Free space \]
|
||
MOVEI B,QSFT
|
||
PUSHJ P,QTABL1
|
||
OASCR [0]
|
||
|
||
OASC [ASCIZ \Swap area \]
|
||
MOVEI B,TSWAPA
|
||
HLL B,QPTR
|
||
MOVE D,QPTR
|
||
HRRI D,QACT
|
||
QSWAPT: SKIPE (D)
|
||
JRST QSWAP1
|
||
MOVE C,(B)
|
||
SUB C,NUDSL
|
||
SKIPGE C
|
||
MOVEI C,0
|
||
OJUST 5,C
|
||
QSWAP2: OASCI ^I
|
||
AOBJN D,.+1
|
||
AOBJN B,QSWAPT
|
||
OASCR [0]
|
||
OASC [ASCIZ \Free swap area \]
|
||
MOVEI B,QSFTS
|
||
PUSHJ P,QTABL1
|
||
POPJ P,
|
||
|
||
QSWAP1: OASC [ASCIZ / --/]
|
||
JRST QSWAP2
|
||
|
||
QTABL1: PUSH P,C
|
||
MOVE C,QPTR
|
||
HRRI C,QACT
|
||
HLL B,QPTR
|
||
QTABL3: SKIPE (C)
|
||
JRST QTABL2
|
||
OJUST 5,(B)
|
||
QTABL4: OASCI ^I
|
||
AOBJN C,.+1
|
||
AOBJN B,QTABL3
|
||
OASCR [0]
|
||
POP P,C
|
||
POPJ P,
|
||
QTABL2: OASC [ASCIZ \ --\]
|
||
JRST QTABL4
|
||
|
||
QTABLE: HLL B,QPTR
|
||
OJUST 5,(B)
|
||
OASCI ^I
|
||
AOBJN B,QTABLE+1
|
||
OASCR [0]
|
||
POPJ P,
|
||
|
||
|
||
; point at user vector -- up to MAXUSR users
|
||
GATHER: MOVEI A,USERS
|
||
MOVEM A,N
|
||
MOVEM A,M ; ptr to vector
|
||
; zero total of users
|
||
SETZM TUS ; users
|
||
SETZM TPIGS ; users over quota
|
||
SETZM TFAT ; total excess
|
||
SETZM TBACON ; average excess
|
||
PUSHJ P,GETMFD
|
||
|
||
GATHE1: PUSHJ P,MFDN ; get a user id into C
|
||
JRST GATHEX
|
||
JUMPE C,GATHE1 ; loop if empty slot
|
||
MOVEM C,USRNAM ; username
|
||
.SUSET [.SSNAM,,C] ; set to it
|
||
; individual user stats
|
||
PUSHJ P,USRDSK
|
||
JRST GATHE1
|
||
PUSHJ P,USRVEC ; add to vector
|
||
AOS TUS
|
||
JRST GATHE1 ; loop
|
||
|
||
GATHEX: MOVE A,TFAT ; calculate avg blks for pigs
|
||
MOVE B,TPIGS
|
||
PUSHJ P,AVG
|
||
MOVEM A,TBACON
|
||
|
||
MOVE A,TBQUOT ; calculate avg blks for quota
|
||
MOVE B,TUQUOT
|
||
PUSHJ P,AVG
|
||
MOVEM A,TAQUOT
|
||
|
||
MOVE A,TBALLO ; calculate avg blks for alloc
|
||
MOVE B,TUALLO
|
||
PUSHJ P,AVG
|
||
MOVEM A,TAALLO
|
||
POPJ P,
|
||
|
||
; average, given total and number of instances (as fixes), return a fix
|
||
AVG: PUSH P,B
|
||
FLOAT A
|
||
FLOAT B
|
||
FDVR A,B
|
||
FIX A
|
||
MOVE A,B
|
||
POP P,B
|
||
POPJ P,
|
||
|
||
; * here to get average number of blocks per user on disk *
|
||
|
||
;This comment is wrong!
|
||
; makes a good guess at number of free blocks on disks by finding out
|
||
; number of packs, and number of free blocks on each, subtracting that from
|
||
; number of packs times 5000 blocks per pack minus 200 ufd blocks and 1 mfd, 1 tut
|
||
; per pack.
|
||
|
||
; Puts results out in ALLBL (total number of blocks)
|
||
; and FREEBL (number of blocks free)
|
||
|
||
DSKAV: PUSHJ P,QNUM ; how many packs
|
||
PUSHJ P,QRES ; any reserved?
|
||
PUSHJ P,DSKALL ; total disk blocks
|
||
PUSHJ P,DSKFRE ; free disk blocks
|
||
PUSHJ P,SWPFRE ; free swapping blocks
|
||
PUSHJ P,DSKMFD ; get # of users, blocks/user
|
||
POPJ P,
|
||
|
||
; * number of packs in system *
|
||
|
||
; nqs/ # of packs
|
||
; qtuto/ -n,,qtuto
|
||
; tutsiz/ # of blocks per tut
|
||
|
||
QNUM: PUSH P,A
|
||
MOVE A,[SQUOZE 0,NQS]
|
||
.EVAL A,
|
||
.VALUE [ASCIZ /:.EVAL OF NQS FAILED/]
|
||
MOVEM A,NQS
|
||
MOVNS A
|
||
HRLS A
|
||
HRRI A,QTUTO
|
||
MOVEM A,QPTR
|
||
; get number blocks for a tut
|
||
MOVE A,[SQUOZE 0,NTUTBL]
|
||
.EVAL A,
|
||
.VALUE [ASCIZ /:.EVAL OF SYMBOL IN A FAILED/]
|
||
MOVEM A,TUTSIZ
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
; any reserved packs in system??
|
||
|
||
QRES: PUSH P,A
|
||
MOVE A,[SQUOZE 0,QRSRVP]
|
||
SETOM TUTRSR
|
||
.EVAL A,
|
||
SETZB A,TUTRSR
|
||
MOVEM A,QRSRVP
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
; * free blocks in system *
|
||
|
||
; freebl/ free blocks in system
|
||
|
||
DSKFRE: PUSH P,A
|
||
PUSH P,B
|
||
MOVE A,[QSFT,,[SQUOZE 0,QSFT]]
|
||
PUSHJ P,GETQ
|
||
MOVEI B,QSFT
|
||
PUSHJ P,QTOTAL
|
||
MOVEM A,FREEBL
|
||
MOVEI B,0
|
||
HLL B,QPTR
|
||
SETZ A,
|
||
DSKFR1: SKIPE TRESRV(B)
|
||
JRST DSKFR2
|
||
SKIPL QSFT(B)
|
||
ADD A,QSFT(B)
|
||
DSKFR2: AOBJN B,DSKFR1
|
||
MOVEM A,FRUNAL
|
||
MOVNS A
|
||
ADDM A,FREEBL
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
; * free swapping blocks *
|
||
|
||
; freesw/ free swapping blocks
|
||
|
||
SWPFRE: PUSH P,A
|
||
PUSH P,B
|
||
MOVE A,[QSFTS,,[SQUOZE 0,QSFTS]]
|
||
PUSHJ P,GETQ
|
||
MOVEI B,QSFTS
|
||
PUSHJ P,QTOTAL
|
||
MOVEM A,FREESW
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
; * getloc of (in ac A) symbol to symbol+nqs *
|
||
|
||
; qtuto/ first pack
|
||
; ...
|
||
; qtuto+nqs-1/ last pack
|
||
|
||
GETQ: PUSH P,B
|
||
MOVE B,QPTR
|
||
HLR B,A
|
||
MOVE A,(A)
|
||
.EVAL A,
|
||
.VALUE [ASCIZ /:.EVAL OF SYMBOL IN A FAILED/]
|
||
HRLS A
|
||
HRR A,B
|
||
.GETLOC A,
|
||
ADD A,[1,,1]
|
||
AOBJN B,.-2
|
||
POP P,B
|
||
POPJ P,
|
||
|
||
|
||
; A/ <table>,, symbol
|
||
GETUT: PUSH P,B
|
||
PUSH P,C
|
||
HRLZ C,A ; C/ symbol,,0
|
||
HLRZ A,A ; A/ table nqs long
|
||
MOVE B,QPTR ; B/ -nqs,,qtuto
|
||
|
||
SIZLUP: HRL A,(B)
|
||
ADD A,C ; offset by QTUTO
|
||
.GETLOC A,
|
||
AOS A
|
||
AOBJN B,SIZLUP
|
||
POP P,C
|
||
POP P,B
|
||
POPJ P,
|
||
|
||
; * allocations *
|
||
|
||
; swapal/ swapping allocation
|
||
; allbl/ total of system blocks
|
||
|
||
DSKALL: PUSH P,A
|
||
PUSH P,B
|
||
PUSH P,C
|
||
PUSH P,D
|
||
|
||
; read in qtuto table
|
||
MOVE A,[QTUTO,,[SQUOZE 0,QTUTO]]
|
||
PUSHJ P,GETQ
|
||
|
||
; find out which packs are active
|
||
MOVE A,[QACT,,[SQUOZE 0,QACT]]
|
||
PUSHJ P,GETQ
|
||
|
||
; now total on-line disk packs
|
||
SETZ A,
|
||
MOVEI B,QACT
|
||
HLL B,QPTR
|
||
SKIPN (B) ; offline?
|
||
AOS A
|
||
AOBJN B,.-2
|
||
MOVEM A,NQSONL
|
||
|
||
; find out pack numbers for each drive
|
||
MOVE A,[QPKID,,[SQUOZE 0,QPKID]]
|
||
PUSHJ P,GETQ
|
||
|
||
; find out which packs are allocated
|
||
SKIPN TUTRSR ; reservations in tut?
|
||
JRST OLDRSR
|
||
|
||
MOVE A,[TRESRV,,QTRSRV]
|
||
SKIPE QRSRVP ; any reserved packs in system?
|
||
PUSHJ P,GETUT
|
||
JRST GSWAPA
|
||
|
||
OLDRSR: MOVE A,[TRESRV,,[SQUOZE 0,QRESRV]]
|
||
PUSHJ P,GETQ ; else in table
|
||
|
||
; get size of packs
|
||
GSWAPA: MOVE A,[TLASTB,,QLASTB]
|
||
PUSHJ P,GETUT
|
||
|
||
; get swapping allocations
|
||
MOVE A,[TSWAPA,,QSWAPA]
|
||
PUSHJ P,GETUT
|
||
|
||
; start by getting number of ufds
|
||
MOVE A,[SQUOZE 0,NUDSL]
|
||
.EVAL A,
|
||
.VALUE [ASCIZ /:.EVAL OF NUDSL FAILED/]
|
||
MOVEM A,NUDSL
|
||
|
||
; get total swapping allocation, fixed up by removing blocks
|
||
; allocated for UFDs
|
||
HLLZ C,QPTR
|
||
MOVEI B,0
|
||
GSWAP1: SKIPE QACT(C)
|
||
JRST GSWAP2
|
||
MOVE A,TSWAPA(C)
|
||
SUB A,NUDSL
|
||
SKIPLE A
|
||
ADD B,A
|
||
GSWAP2: AOBJN C,GSWAP1
|
||
MOVEM B,SWAPAL
|
||
|
||
; calculate total blocks per pack
|
||
MOVE B,QPTR
|
||
HRRI B,TLASTB
|
||
MOVE C,QPTR
|
||
HRRI C,TSWAPA
|
||
MOVE D,QPTR
|
||
HRRI D,TSIZES
|
||
|
||
DSKTOT: MOVE A,(B)
|
||
; get greater of nudsl and swapa into 0
|
||
MOVE 0,NUDSL
|
||
CAMGE 0,(C)
|
||
MOVE 0,(C)
|
||
SUB A,0
|
||
; subtract mfd and tut if not already part of swapa
|
||
CAIGE 0,2500.
|
||
SUB A,TUTSIZ ; flush tut blocks
|
||
MOVEM A,(D)
|
||
AOBJN B,.+1
|
||
AOBJN C,.+1
|
||
AOBJN D,DSKTOT
|
||
|
||
; calculate total blocks by adding all packs
|
||
MOVEI B,TSIZES
|
||
PUSHJ P,QTOTAL
|
||
MOVEM A,ALLBL
|
||
|
||
; restore acs and return
|
||
POP P,D
|
||
POP P,C
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
; total a table nqs long -- ignore inactive packs
|
||
QTOTAL: PUSH P,C
|
||
MOVE C,QPTR
|
||
HRRI C,QACT
|
||
HLL B,QPTR
|
||
SETZ A,
|
||
QTOTA1: SKIPE (C)
|
||
JRST QTOTA2
|
||
SKIPL (B)
|
||
ADD A,(B)
|
||
QTOTA2: AOBJN C,.+1
|
||
AOBJN B,QTOTA1
|
||
POP P,C
|
||
POPJ P,
|
||
|
||
; total users and average per user
|
||
|
||
; aver/ average blocks per user
|
||
; tus/ total users
|
||
|
||
DSKMFD: PUSH P,A
|
||
PUSH P,B
|
||
|
||
SKIPE B,TUS
|
||
JRST DSKMF1
|
||
PUSHJ P,GETMFD
|
||
PUSHJ P,MFDN
|
||
SKIPA
|
||
AOJA B,.-2
|
||
MOVEM B,TUS
|
||
|
||
; now compute average blocks per user
|
||
DSKMF1: MOVE A,ALLBL
|
||
SUB A,FREEBL
|
||
IDIV A,B
|
||
MOVEM A,AVER
|
||
.CLOSE MCH,
|
||
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
; * next username from mfd *
|
||
|
||
; C/ username in sixbit
|
||
MFDN: AOS MFDPTR
|
||
AOS C,MFDPTR
|
||
CAILE C,MFDPTR+1777
|
||
POPJ P,
|
||
SKIPN C,(C)
|
||
JRST MFDN
|
||
AOS (P)
|
||
POPJ P,
|
||
|
||
; * add info on a user to free block *
|
||
|
||
; get 6 word block
|
||
USRVEC: MOVEI A,%USRBLK
|
||
ADDB A,FREEPT
|
||
|
||
; put out data
|
||
MOVE 0,USRNAM ; username
|
||
MOVEM 0,%USER(A)
|
||
MOVE 0,UFILES ; # files
|
||
MOVEM 0,%FILES(A)
|
||
MOVE 0,ULINKS ; # links
|
||
MOVEM 0,%LINKS(A)
|
||
MOVE 0,UBLCKS ; # blocks
|
||
MOVEM 0,%BLCKS(A)
|
||
MOVE 0,UQUOTA ; quota
|
||
MOVEM 0,%QUOTA(A)
|
||
MOVE 0,UALLOC
|
||
MOVEM 0,%ALLOC(A)
|
||
MOVE 0,UPACKN
|
||
MOVEM 0,%PACKN(A)
|
||
MOVE 0,UBKFLS ; blocks/file
|
||
MOVEM 0,%BLKAV(A)
|
||
|
||
; update cptr to pointers
|
||
MOVEM A,(N)
|
||
SUB N,[(1)]
|
||
ADDI N,1
|
||
POPJ P,
|
||
|
||
; * typeout information on a given user *
|
||
; a/ ptr to data block
|
||
|
||
TYPOUT: PUSH P,A
|
||
PUSH P,B
|
||
MOVE B,A
|
||
|
||
; type out data
|
||
OSIX %USER(B) ; user-id
|
||
OASCI ^I
|
||
OJUST 3,%FILES(B) ; # file
|
||
OASCI ^I
|
||
OJUST 3,%LINKS(B) ; # links
|
||
OASCI ^I
|
||
OJUST 4,%BLCKS(B) ; # blocks
|
||
; give him a * if over quota
|
||
SKIPE TQUO
|
||
SKIPG A,%QUOTA(B) ; has quota?
|
||
JRST TYPBLK
|
||
CAMGE A,%BLCKS(B)
|
||
OASCI "*
|
||
TYPBLK: SKIPG TQUO
|
||
JRST TYPALC
|
||
SKIPG TALLO
|
||
JRST TYPOU1
|
||
OASCI ^I
|
||
SKIPG %ALLOC(B)
|
||
JRST TYPQUO
|
||
; here if has alloc. (print quota only if different)
|
||
TYPALL: MOVE A,%QUOTA(B)
|
||
CAMN A,%ALLOC(B)
|
||
JRST TYPAL1
|
||
OJUST 4,%QUOTA(B)
|
||
TYPAL1: OASCI ^I
|
||
OJUST 4,%ALLOC(B)
|
||
JRST TYPOU1
|
||
; here if only has quota
|
||
TYPQUO: OJUST 4,%QUOTA(B)
|
||
OASCI ^I
|
||
|
||
; restore acs and return
|
||
TYPOU1: OASCI ^I
|
||
SKIPE %PACKN(B)
|
||
OJUST 2,%PACKN(B)
|
||
OASCI ^I
|
||
OFLOAT %BLKAV(B) ; blocks/file
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
TYPALC: SKIPG TALLO
|
||
JRST TYPOU1
|
||
OASCI ^I
|
||
OJUST 4,%ALLOC(B)
|
||
JRST TYPOU1
|
||
|
||
; * read in mfd *
|
||
|
||
GETMFD: SKIPE MFDBUF+MDNAMP
|
||
JRST GETMFX
|
||
.OPEN MCH,MFDDIR
|
||
.VALUE [ASCIZ !:CANT OPEN M.F.D.!]
|
||
MOVE A,[-2000,,MFDBUF]
|
||
.IOT MCH,A
|
||
JUMPL A,TINY
|
||
.CLOSE MCH,
|
||
GETMFX: MOVE A,MFDBUF+MDNAMP
|
||
ADDI A,MFDBUF-2 ; aos's first, cretin...
|
||
MOVEM A,MFDPTR
|
||
POPJ P,
|
||
|
||
TINY: .VALUE [ASCIZ !:M.F.D. LESS THAN 2000 WORDS LONG?!]
|
||
|
||
; * single user statistics gatherer *
|
||
|
||
NOUFD: OASCI ""
|
||
OSIX USRNAM
|
||
OASCR [ASCIZ \" is not the name of a directory.\]
|
||
JRST KILL
|
||
|
||
USRDSK: PUSH P,D
|
||
PUSH P,E
|
||
|
||
; read ufd in
|
||
.OPEN CH,UDIR
|
||
JRST USRLSR
|
||
MOVE A,[-2000,,FDIR]
|
||
.IOT CH,A
|
||
.CLOSE CH,
|
||
|
||
; initialize world
|
||
SETZB C,D
|
||
SETZB E,F
|
||
SETZM UFILES
|
||
SETZM ULINKS
|
||
SETZM UBLCKS
|
||
SETZM UBKFLS
|
||
SETZM UQUOTA
|
||
SETZM UALLOC
|
||
SETZM UPACKN
|
||
SETZM OLDC
|
||
|
||
; quota and number of blocks
|
||
MOVE B,FDIR+UDBLKS
|
||
HLREM B,UQUOTA
|
||
SKIPGE B
|
||
SETZM UQUOTA
|
||
HRREM B,UBLCKS
|
||
SKIPG A,UQUOTA
|
||
JRST L69
|
||
CAML A,UBLCKS
|
||
JRST L69
|
||
MOVE A,UBLCKS
|
||
SUB A,UQUOTA
|
||
ADDM A,TFAT
|
||
AOS TPIGS
|
||
|
||
; pack and allocation
|
||
L69: HRRE B,FDIR+UDALLO
|
||
SKIPLE B ; if negative or zero (UALLOC is 0 already)
|
||
MOVEM B,UALLOC
|
||
|
||
HLRZ E,FDIR+UDALLO
|
||
JUMPE E,L105
|
||
MOVEM E,UPACKN
|
||
SKIPN TUTRSR
|
||
JRST O69
|
||
|
||
MOVE A,QPTR ; here for new style reservations
|
||
HLLZ A,A ; done by pack number rather than drive
|
||
DRLOOP: SKIPL QACT(A) ; drive off line?
|
||
CAME E,QPKID(A)
|
||
JRST DRNEXT
|
||
ADDM B,PACK(A)
|
||
JRST L105
|
||
DRNEXT: AOBJN A,DRLOOP
|
||
JRST L105
|
||
|
||
O69: ADDM B,PACK(E) ; for old style reservation hackery
|
||
|
||
L105: MOVE B,UDNAMP+FDIR
|
||
ADDI B,FDIR
|
||
|
||
L1: CAILE B,FDIR+1773
|
||
JRST UNUM
|
||
SKIPN (B)
|
||
JRST NEXTFL
|
||
MOVE E,UNRNDM(B)
|
||
TLNE E,UNIGFL
|
||
JRST NEXTFL
|
||
TLNE E,1
|
||
AOSA ULINKS ; was a link
|
||
AOS UFILES ; was a regular file
|
||
|
||
; move to next file
|
||
NEXTFL: ADDI B,LUNBLK
|
||
JRST L1
|
||
|
||
; finish calculations and exit
|
||
|
||
; calculate blocks/file
|
||
UNUM: MOVE A,UBLCKS
|
||
FLOAT A
|
||
MOVE B,UFILES
|
||
FLOAT B
|
||
FDVR A,B
|
||
MOVEM A,UBKFLS
|
||
|
||
; add to totals
|
||
SKIPLE E,UFILES
|
||
ADDM E,TFL
|
||
SKIPLE E,ULINKS
|
||
ADDM E,TLK
|
||
SKIPLE E,UBLCKS
|
||
ADDM E,TBL
|
||
SKIPG UALLOC
|
||
JRST UPDUSR
|
||
AOS TUALLO ; here for allocated directory
|
||
ADDM E,TBALLO
|
||
JRST UPDUS1
|
||
UPDUSR: SKIPG UQUOTA
|
||
JRST UPDUS1
|
||
AOS TUQUOT ; here for quota'ed directory
|
||
ADDM E,TBQUOT
|
||
UPDUS1: SKIPLE E,UQUOTA
|
||
ADDM E,TQUO
|
||
SKIPLE E,UALLOC
|
||
ADDM E,TALLO
|
||
|
||
; go here if no files in dir
|
||
ZEROES: AOS -2(P)
|
||
USRLSR: POP P,E
|
||
POP P,D
|
||
POPJ P,
|
||
|
||
; byte pointer table
|
||
DESCBP: 440600
|
||
360600
|
||
300600
|
||
220600
|
||
140600
|
||
060600
|
||
; * buffers *
|
||
MAXUSR==512.
|
||
|
||
USERS: BLOCK MAXUSR ; this is largest number of users prog will handle
|
||
|
||
FREEPT: FREESP+1-%USRBLK
|
||
FREESP: BLOCK MAXUSR*%USRBLK ; free storage buffer
|
||
|
||
PDL: BLOCK 100
|
||
FDIR: BLOCK 2000
|
||
BUF: BLOCK 20.
|
||
|
||
; variables
|
||
SORTX: -1,,0
|
||
CPTR: 0
|
||
CPTR1: 0
|
||
OLDC: 0
|
||
|
||
; * variables used for getting system info *
|
||
|
||
TUTRSR: 0 ; non-zero if new style reservation stuff
|
||
TUTSIZ: 0 ; number of blocks in tut (NTUTBL)
|
||
|
||
NQS: 0 ; number of packs
|
||
NQSONL: 0 ; number of packs online
|
||
QPTR: 0 ; -nqs,,qtuto
|
||
QRSRVP: 0 ; any reserved packs?
|
||
NUDSL: 0 ; number of ufds allowed
|
||
|
||
QTUTO: BLOCK 10 ; location of tut for drives
|
||
|
||
TLASTB: BLOCK 10 ; drive sizes (rp02 or rp03)
|
||
TRESRV: BLOCK 10 ; reserved? (-1 if is)
|
||
TSWAPA: BLOCK 10 ; swapping allocations
|
||
|
||
QACT: BLOCK 10 ; disk active?
|
||
QPKID: BLOCK 10 ; pack numbers
|
||
TSIZES: BLOCK 10 ; calculated sizes (exclude ufds and mfd and tut)
|
||
QSFT: BLOCK 10 ; free file space
|
||
QSFTS: BLOCK 10 ; free swap space
|
||
PACK: BLOCK 10 ; total allocated on each drive
|
||
|
||
; * status variables *
|
||
|
||
; single user totals
|
||
USRNAM: 0 ; user
|
||
UFILES: 0 ; # of files
|
||
ULINKS: 0 ; # of links
|
||
UBLCKS: 0 ; number of blocks in ufd
|
||
UBKFLS: 0 ; blocks/file average
|
||
UQUOTA: 0 ; quota
|
||
UALLOC: 0 ; allocation
|
||
UPACKN: 0 ; allocated pack number
|
||
|
||
; system wide totals
|
||
TUS: 0 ; total # users
|
||
TUALLO: 0 ; total # allocated users
|
||
TUQUOT: 0 ; total # quota'ed users
|
||
|
||
TPIGS: 0 ; users over quota
|
||
TFAT: 0 ; total excess for TPIGS
|
||
TBACON: 0 ; average pigness of TPIGS
|
||
|
||
TFL: 0 ; total files
|
||
TLK: 0 ; total links
|
||
|
||
TBL: 0 ; total blocks
|
||
TBALLO: 0 ; total blocks in allocated directories
|
||
TBQUOT: 0 ; total blocks in quota'ed directories
|
||
|
||
TAV: 0 ; average b/f over system
|
||
TAALLO: 0 ; average b/u for allocated directories
|
||
TAQUOT: 0 ; average b/u for quota'ed directories
|
||
|
||
TQUO: 0 ; total of quotas
|
||
TALLO: 0 ; total of allocations
|
||
|
||
; block for cretinous mfd
|
||
MFDPTR: 0
|
||
MFDBUF: BLOCK 2000.
|
||
|
||
; disk system stats
|
||
FREESW: 0 ; free swapping blocks
|
||
SWAPAL: 0 ; swapping allocation
|
||
FREEBL: 0 ; free disk blocks
|
||
FRUNAL: 0 ; free unallocated blocks
|
||
ALLBL: 0 ; total number of blocks
|
||
AVER: 0 ; average number of blocks per user directory
|
||
|
||
DATE: 0 ; date dskuse was run
|
||
TIME: 0 ; time dskuse was run
|
||
|
||
; * I/O variables *
|
||
|
||
BOTH: 0 ; flag for double dskuse ("&")
|
||
|
||
; files
|
||
UDIR: SIXBIT / &DSK.FILE.(DIR) /
|
||
MFDDIR: SIXBIT / &DSKM.F.D.(FILE)/
|
||
|
||
OUTPUT: SIXBIT / !TPLDSKUSEOUTPUT/
|
||
RSYSNM: 0 ; sname of user
|
||
SYSNAM: 0 ; which system? dm, ai, or ml?
|
||
|
||
; ================================================================
|
||
; read a command line
|
||
; ================================================================
|
||
|
||
COMMND: BLOCK 20
|
||
COMPTR: 0
|
||
|
||
; set up buffer
|
||
READ: PUSH P,A
|
||
PUSH P,B
|
||
SETZM COMMND
|
||
MOVE [COMMND,,COMMND+1]
|
||
BLT 0,COMPTR-1
|
||
; command reader
|
||
RCMD: MOVE B,[440700,,COMMND]
|
||
MOVEM B,COMPTR
|
||
MOVEI C,0
|
||
RCMD1: .IOT TYIC,A
|
||
CAIN A,177
|
||
JRST RUB
|
||
CAIN A,^D
|
||
JRST RREPEA
|
||
CAIN A,^L
|
||
JRST RCLEAR
|
||
CAIN A,^J
|
||
JRST RCMD1
|
||
CAIN A,^Q
|
||
JRST RQUOTE
|
||
CAIN A,^M
|
||
JRST RCMDX
|
||
RCMDL: IDPB A,B
|
||
CAMGE B,[350700,,COMMND+17]
|
||
AOJA C,RCMD1
|
||
|
||
RCFUL: IDPB A,B
|
||
MOVEI A,15
|
||
IDPB A,B
|
||
|
||
RCMDX: IDPB A,B
|
||
MOVEI A,0
|
||
IDPB A,B
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
RREPEA: .IOT TCMD,[^M]
|
||
.IOT TCMD,[^J]
|
||
JRST REPPER
|
||
RCLEAR: .IOT TCMD,[^P]
|
||
.IOT TCMD,["C]
|
||
REPPER: .IOT TCMD,["*]
|
||
MOVEI A,COMMND
|
||
HRLI A,440700
|
||
REP1: ILDB A
|
||
JUMPE RCMD1
|
||
.IOT TCMD,
|
||
JRST REP1
|
||
|
||
RQUOTE: IDPB A,B
|
||
CAML B,[350700,,COMMND+17]
|
||
JRST RCFUL
|
||
SETOM QUTFLG
|
||
AOS C
|
||
.IOT TYIC,A
|
||
SETZM QUTFLG'
|
||
JRST RCMDL
|
||
|
||
RUB: PUSHJ P,RUBBER
|
||
JRST RCMD
|
||
JRST RCMD1
|
||
|
||
RUBBER: SOJL C,[POPJ P,] ; erasure rubout handler
|
||
MOVEI A,0
|
||
DPB A,B
|
||
.IOT TCMD,[^P]
|
||
.IOT TCMD,["X]
|
||
ADD B,[070000,,]
|
||
TLNE B,400000
|
||
ADD B,[347777,,-1]
|
||
AOS (P)
|
||
POPJ P,
|
||
|
||
; ===================================================================
|
||
; command line reading and parsing section
|
||
; ===================================================================
|
||
|
||
; read a file spec
|
||
SCNAME: PUSH P,D
|
||
MOVEI D,OUTPUT
|
||
PUSH P,A
|
||
PUSH P,B
|
||
PUSH P,C
|
||
MOVSI C,-2
|
||
HRRI C,1(D)
|
||
JRST SCNONE
|
||
SCNGET: HRRZ A,(D)
|
||
CAIE A,'TPL
|
||
JRST SCNONE
|
||
MOVEI A,'DSK
|
||
HRRM A,(D)
|
||
SCNONE: PUSHJ P,GETSYL
|
||
JUMPE B,SCNX
|
||
CAIE A,':
|
||
JRST .+3
|
||
HLRZM B,(D)
|
||
JRST SCNGET
|
||
CAIE A,';
|
||
JRST SCNNMN
|
||
MOVEM B,3(D)
|
||
JRST SCNGET
|
||
SCNNMN: MOVEM B,(C)
|
||
JUMPL A,SCNX
|
||
CAIE A,',
|
||
AOBJN C,SCNGET
|
||
SCNX: POP P,C
|
||
POP P,B
|
||
POP P,A
|
||
POP P,D
|
||
POPJ P,
|
||
|
||
; get a syllable from command buffer
|
||
GETSYL: PUSH P,C
|
||
PUSH P,[0]
|
||
MOVEI B,(P)
|
||
HRLI B,440600
|
||
GETSLP: PUSHJ P,GETCCA
|
||
JUMPL A,GETSX
|
||
SETO E,
|
||
CAIN A,^Q
|
||
JRST GETQOT
|
||
SUBI A,40
|
||
JUMPL A,GETSX
|
||
JUMPE A,GETSP
|
||
CAIN A,'_
|
||
JRST GETSX
|
||
CAIE A,':
|
||
CAIN A,';
|
||
JRST GETSX
|
||
GETSPT: CAIL A,100
|
||
SUBI A,40
|
||
TLNN B,770000
|
||
JRST GETSLP
|
||
IDPB A,B
|
||
JRST GETSLP
|
||
|
||
GETQOT: ILDB A,COMPTR
|
||
SUBI A,40
|
||
JUMPGE A,GETSPT
|
||
JRST GETSX
|
||
GETSP: TLNE B,400000
|
||
JRST GETSLP
|
||
GETSX: POP P,B ; character word
|
||
POP P,C
|
||
POPJ P,
|
||
|
||
GETCCA: ILDB A,COMPTR
|
||
JUMPE A,GETCCX
|
||
CAIN A,^I
|
||
MOVEI A,40
|
||
CAIN A,^M
|
||
JRST GETCCX
|
||
CAIN A,"
|
||
MOVEI A,",
|
||
POPJ P,
|
||
GETCCX: SETOM A
|
||
POPJ P,
|
||
|
||
; ================================================================
|
||
; interrupt handler (tty only)
|
||
; ================================================================
|
||
|
||
ZZZ=.
|
||
|
||
LOC 42
|
||
JSR TSINT
|
||
LOC ZZZ
|
||
|
||
TSINT: 0
|
||
0
|
||
PUSH P,A
|
||
MOVEI A,TYIC
|
||
.ITYIC A,
|
||
JRST TSDIS
|
||
CAIE A,^G
|
||
CAIN A,^S
|
||
JRST TSKILL ; if ^S or ^G typed, quit
|
||
TSDIS: POP P,A
|
||
.DISMIS TSINT+1
|
||
|
||
TSKILL: .IOT TYIC,A
|
||
POP P,A
|
||
.DISMIS [BADCOM]
|
||
|
||
; ================================================================
|
||
; uuo handler (typeout uuos)
|
||
; ================================================================
|
||
|
||
ZZZ==.
|
||
LOC 40
|
||
0
|
||
JSR UUOH
|
||
LOC ZZZ
|
||
UUOCT==0
|
||
UUOTAB: JRST ILUUO
|
||
IRPS X,,[OSIX OASC OASCI OASCR ODEC ODECR OFLOAT OJUST ODATE OTIME]
|
||
UUOCT==UUOCT+1
|
||
X=UUOCT_33
|
||
JRST U!X
|
||
TERMIN
|
||
|
||
UUOMAX==.-UUOTAB
|
||
|
||
UUOD: 0 ; contents of UUO eff addr.
|
||
UUOE: 0 ; UUO effad.
|
||
|
||
UUOH: 0
|
||
PUSH P,A
|
||
PUSH P,B
|
||
PUSH P,C
|
||
PUSH P,D
|
||
MOVEI @40 ; get eff addr. of uuo
|
||
MOVEM UUOE
|
||
MOVE @0
|
||
MOVEM UUOD ; contents of eff adr
|
||
MOVE B,UUOE ; eff adr
|
||
LDB A,[270400,,40] ; get uuo ac,
|
||
LDB C,[330600,,40] ; op code
|
||
CAIL C,UUOMAX
|
||
MOVEI C,0 ; grt=>illegal
|
||
JRST @UUOTAB(C) ; go to proper rout
|
||
|
||
UUORET: POP P,D
|
||
POP P,C
|
||
POP P,B
|
||
POP P,A ; restore ac's
|
||
JRST 2,@UUOH
|
||
|
||
ILUUO: .VALUE [ASCIZ /:ILLEGAL UUO/]
|
||
|
||
UOASCR: SKIPA C,[^M] ; cr for end of type
|
||
UOASC: MOVEI C,0 ; no cr
|
||
HRLI B,440700 ; make ascii pointer
|
||
UOASC1: ILDB A,B ; get char
|
||
JUMPE A,.+3 ; finish?
|
||
PUSHJ P,IOTA
|
||
JRST .-3 ; and get another
|
||
SKIPE A,C ; get saved cr?
|
||
PUSHJ P,IOTA
|
||
JRST UUORET
|
||
|
||
UOASCI: MOVE A,B ; prt ascii immediate
|
||
PUSHJ P,IOTA
|
||
JRST UUORET
|
||
|
||
UOSIX: MOVE B,UUOD
|
||
USXOOP: JUMPE B,UUORET
|
||
LDB A,[360600,,B]
|
||
ADDI A,40
|
||
PUSHJ P,IOTA
|
||
LSH B,6
|
||
JRST USXOOP
|
||
|
||
TENS: 0 ? 10. ? 100. ? 1000. ? 10000. ? 100000.
|
||
|
||
UOJUST: MOVE B,UUOD
|
||
TYOJ1: CAML B,TENS(A)
|
||
JRST UOJUS1
|
||
.IOT TYOC,[40]
|
||
SOJG A,TYOJ1
|
||
UOJUS1: SETZB A,D
|
||
MOVEI C,10.
|
||
JRST UOOCTI+1
|
||
|
||
UODECR: SKIPA D,[^M]
|
||
UODEC: SETZ D,
|
||
MOVEI C,10.
|
||
JRST .+3
|
||
UOOCT: SETZ D,
|
||
MOVEI C,8. ; octal base
|
||
MOVE B,UUOD ; get actual word to prt
|
||
JRST .+3 ; join code
|
||
UODECI: SKIPA C,[10.] ; decimal
|
||
UOOCTI: MOVEI C,8.
|
||
MOVEM C,BASE'
|
||
SKIPN A
|
||
HRREI A,-1 ; a=digit count
|
||
PUSHJ P,UONUM ; print numbr
|
||
SKIPE A,D
|
||
PUSHJ P,IOTA
|
||
JRST UUORET
|
||
|
||
UONUM: IDIV B,BASE
|
||
HRLM C,(P) ; save digit
|
||
SOJE A,UONUM1 ; done if 0
|
||
SKIPG A ; + => more
|
||
SKIPE B ; - => b=0 => done
|
||
PUSHJ P,UONUM ; else more
|
||
UONUM1: HLRZ C,(P) ; retreive digits
|
||
ADDI C,"0 ; make to ascii
|
||
CAILE C,"9 ; is it good dig
|
||
ADDI C,"A-"9-1 ; make hex digit
|
||
PUSHJ P,IOTC
|
||
POPJ P, ; ret
|
||
|
||
UOFLOA: PUSH P,E
|
||
PUSH P,F
|
||
PUSH P,G
|
||
PUSH P,H
|
||
PUSH P,I
|
||
MOVE A,UUOD
|
||
MOVE D,A
|
||
PUSHJ P,NFLOT
|
||
POP P,I
|
||
POP P,H
|
||
POP P,G
|
||
POP P,F
|
||
POP P,E
|
||
JRST UUORET
|
||
|
||
; at this point we enter code abstracted from DDT.
|
||
NFLOT: JUMPE A,FP1A
|
||
|
||
TFL1: MOVEI B,0
|
||
CAMGE A,FT01
|
||
JRST FP4
|
||
CAML A,FT8
|
||
AOJA B,FP4
|
||
FP1A:
|
||
FP3: SETZB C,TEM1 ; CLEAR DIGIT CNTR, C TO RECEIVE FRACTION
|
||
MULI A,400
|
||
ASHC B,-243(A)
|
||
MOVE A,B
|
||
PUSHJ P,FP7
|
||
PUSH P,A
|
||
MOVEI A,".
|
||
PUSHJ P,IOTA
|
||
POP P,A
|
||
MOVNI A,3
|
||
ADD A,TEM1
|
||
MOVE E,C
|
||
FP3A: MOVE D,E
|
||
MULI D,12
|
||
PUSHJ P,FP7B
|
||
SKIPE E
|
||
AOJL A,FP3A
|
||
POPJ P, ; ONE return from OFLT here
|
||
|
||
FP4: MOVNI C,6
|
||
MOVEI F,0
|
||
FP4A: ADDI F,1(F)
|
||
XCT FCP(B)
|
||
SOSA F
|
||
FMPR A,@FCP+1(B)
|
||
AOJN C,FP4A
|
||
PUSH P,EXPSGN(B)
|
||
PUSHJ P,FP3
|
||
PUSH P,A
|
||
MOVEI A,"E
|
||
PUSHJ P,IOTA
|
||
POP P,A
|
||
POP P,D
|
||
MOVE A,D
|
||
PUSHJ P,IOTA
|
||
MOVE A,F
|
||
|
||
FP7: SKIPE A ; AVOID AOSING TEM1, NOT SIGNIFICANT DIGIT
|
||
AOS TEM1
|
||
IDIVI A,12
|
||
HRLM B,(P)
|
||
JUMPE A,FP7A1
|
||
PUSHJ P,FP7
|
||
|
||
FP7A1: HLRZ D,(P)
|
||
FP7B: ADDI D,"0
|
||
PUSH P,A
|
||
MOVE A,D
|
||
PUSHJ P,IOTA
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
; constants
|
||
1.0^32.
|
||
1.0^16.
|
||
FT8: 1.0^8
|
||
1.0^4
|
||
1.0^2
|
||
1.0^1
|
||
FT: 1.0^0
|
||
1.0^-32.
|
||
1.0^-16.
|
||
1.0^-8
|
||
1.0^-4
|
||
1.0^-2
|
||
FT01: 1.0^-1
|
||
FT0=FT01+1
|
||
|
||
TEM1: 0
|
||
|
||
; instructions
|
||
FCP: CAMLE A, FT0(C)
|
||
CAMGE A, FT(C)
|
||
0, FT0(C)
|
||
|
||
EXPSGN: "-
|
||
"+
|
||
|
||
; ====================================================================
|
||
; uuo character output
|
||
; ====================================================================
|
||
|
||
IOTC: PUSH P,A
|
||
MOVE A,C
|
||
PUSHJ P,IOTA
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
IOTA: CAIN A,^P
|
||
JRST IOTAP
|
||
IOTA1: CAIE A,^J
|
||
.IOT TYOC,A
|
||
CAIN A,^M
|
||
.IOT TYOC,[^J]
|
||
POPJ P,
|
||
IOTAP: .IOT TYOC,["^]
|
||
ADDI A,100
|
||
JRST IOTA1
|
||
|
||
; type time
|
||
UOTIME: MOVEI C,":
|
||
JRST UOTUPL
|
||
|
||
; type date
|
||
UODATE: MOVEI C,"/
|
||
UOTUPL: LDB A,[360600,,UUOD]
|
||
ADDI A,40
|
||
PUSHJ P,IOTA
|
||
LDB A,[300600,,UUOD]
|
||
ADDI A,40
|
||
PUSHJ P,IOTA
|
||
PUSHJ P,IOTC
|
||
LDB A,[220600,,UUOD]
|
||
ADDI A,40
|
||
PUSHJ P,IOTA
|
||
LDB A,[140600,,UUOD]
|
||
ADDI A,40
|
||
PUSHJ P,IOTA
|
||
PUSHJ P,IOTC
|
||
LDB A,[060600,,UUOD]
|
||
ADDI A,40
|
||
PUSHJ P,IOTA
|
||
LDB A,[000600,,UUOD]
|
||
ADDI A,40
|
||
PUSHJ P,IOTA
|
||
JRST UUORET
|
||
|
||
; ====================================================================
|
||
; sorter
|
||
; ====================================================================
|
||
|
||
; simple interchange sort
|
||
; A/ sort forward or backward (-1/0)
|
||
VSORT: PUSH P,A
|
||
PUSH P,G
|
||
PUSH P,M
|
||
MOVE F,[CAMG G,(C)]
|
||
SKIPL A
|
||
MOVE F,[CAML G,(C)]
|
||
HRRZS A
|
||
MOVE D,M
|
||
POP D,(D)
|
||
AOS D
|
||
MOVEM D,E
|
||
VSORT1: SETZM K
|
||
MOVE D,E
|
||
AOBJP D,.+1
|
||
SOS D
|
||
MOVEM D,E
|
||
VSORT2: AOBJP D,VSORTX
|
||
MOVE C,(D)
|
||
ADD C,A
|
||
MOVE B,-1(D)
|
||
ADD B,A
|
||
MOVE G,(B)
|
||
XCT F
|
||
JRST VSORT2
|
||
EXCH G,(D)
|
||
EXCH G,-1(D)
|
||
EXCH G,(D)
|
||
JUMPL K,VSORT2
|
||
SETOM K
|
||
MOVEM D,E
|
||
POP E,(E)
|
||
POP E,(E)
|
||
HRRZ B,E
|
||
HRRZ C,M
|
||
CAMGE B,C
|
||
AOBJN E,.+1
|
||
JRST VSORT2
|
||
VSORTX: JUMPL K,VSORT1
|
||
POP P,M
|
||
POP P,G
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
END START
|