1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-01 01:19:17 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

7081 lines
233 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE F11 - Program to manipulate FILES-11 structures on TOPS-10 disks
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1988. ALL RIGHTS RESERVED.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
;TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
;AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
;SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
SALL
SEARCH UUOSYM
.REQUE REL:WILD, REL:SCAN
TWOSEG
RELOC 400000
RELOC 0
LOWSEG=.
RELOC
.DIRECT FLBLST
VMAJ==2 ;MAJOR VERSION
VMIN==0 ;MINOR VERSION
VWHO==0 ;WHO DONE IT
Comment @
F11 is a cheap program to create, destroy, and manipulate
FILES-11 structures and files.
@
SUBTTL Revision History
VER==1 ;7-Jan-85
; Duplicate some of the functionality of FESET with known
; compiler
VER==2 ;6-Nov-85
; Teach NXTFDB to ignore files with a file number of zero if the
; file being matched is non-null. Seems F11ACP does strange and
; wonderful things when dealing with files (such as leaving the
; directory entry and just zeroing the FHB). Fix a few bugs in
; image mode PUT code so first free byte gets set up correctly.
VER==3 ;1-Jan-86
; Fix "?NO WORD FOR INPUT" - remove instruction at EOFBYT+22L.
; Fix "?Ill UUO at..." - pop T3 off stack before POPJ at FCRLF+4L
; Fix "?Illegal switch" - forbid using "=" for switches @ILLSWT+6L
; RSX20F allows null file names! - make NXTFDB check name AND type
; before declaring directory slot as "null"
; LIBRARY files are not ascii - add .OLB and .SML to IMGTBL.
; Adding 33rd file to a UFD causes problems. Create EXPDIR
; to expand a UFD (or MFD) by one block and make it work.
; Add ASS FOO:=BLAH/IMAGE to allow reading a file which is a
; "disk image" file - ie: 1:1 correspondence between
; tops10 data blocks and a real disk.
; Do some things to make a F11 maintained "volume" acceptable
; to the RSX "VFY" utility (so it can recover lost blocks
; or simply verify the correctness of the volume)
;
; o Create TOPS10.NDL;n files in [0,0] to occupy the space
; between physical block 0 and the 1st block of FE.SYS.
; o Stop setting the "dirty" bits in the Storage Control
; Block in BITMAP.SYS.
; o Insert the "max # of retrieval pointers possible"
; in the proper slot when the FHB is initialized.
; o Insert the "BMAX" word into the Storage Control Block.
; (it contains a copy of the last valid LBN in volume).
VER==4 ;25-Feb-86
; Page marks get lost when PUT onto the front end file.
; Fix up C$PUTF so it considers line terminators as BOTH
; line terminators AND as textual characters of some sort.
VER==5 ;25-Feb-87
; Changes to make the volume a VAX/VMS FILES-11 level 1 volume.
;
; Add SETCPT to automatically select 16 bit mode as required.
; Note 16 bit mode doesn't work very well without RPXKON fixes.
;
; Use RSX/VMS "directory names" rather than UICs.
; Allow delete of EMPTY .dir files.
; Allow /NOCHECK to override checks for undeltable files.
; Correct usage of FSEQ/UFSQ and FRNO and UFX0. Always
; read old FHB at INIFHB so we can bump up FSEQ each re-use.
; Always zero newly acquired blocks in INDEXF so FSEQ starts at 0.
; Fix NXTDIR to ignore deleted directory files.
; Don't assume the "TMP166" words will be all blanks since
; RSX+ and VMS puts the volume label there.
; Truncate version to 15 bits as VMS doesn't like 16 bits.
; Fix bug @SIXIN4 causing bad wildcarding with 9 char file names.
; Don't put spaces or lower case in date/time fields as this
; confuses VAX/VMS DIRECTORY/DATE. Support either on input.
VER==6 ;10-Dec-87
; Teach the DESTROY command to find the Files-11 home block
; and zero it out. This makes sure that if F11 is always used
; to both create and destroy front end areas, -20F will never
; stumble across an obsolete home block and try to use it.
; If a pack is refreshed and FE.SYS disappears by itself, you
; may still need to run FEDEL.
VER==100
;4-Nov-87 DPM
;Create version 2(100) from original ADP version
; o Allow commands to work when the command name is really more
; than six characters. Hack FNDIDX to prune results down too.
; o Make sure that all blocks in the FE.SYS file are written
; during INItialization so that a DIR of FE.SYS[1,4] will
; not have zero written blocks.
VER==101
;12-Feb-88 JJF
;Merge in newer ADP version (7) so that the best of both worlds
;is preserved.
;Also put in a DEC copyright statement.
VER=102
;11-May-88 JJF
;Add a SETZM OPNBLK+.OPBUF at OPNVIL+a few so that the open
;of the Files-11 area won't trash the listing output file byte
;pointer. QAR# T10L342_00048.
LOC <.JBVER=137>
EXP <%%F11==<BYTE(3)VWHO(9)VMAJ(6)VMIN(18)VER>>
RELOC
SEARCH $SCNDC,MACTEN
EXTERN .TYOCH ;FORCE SCAN TO LOAD WILD SUBROUTINES
; THESE ACS ARE IN ADDITION TO THOSE DEFINED IN $SCNDC FOR SCAN
DEFINE BIT,<1B<BITNUM==<BITNUM+1>>>
BITNUM==-1
F=0
X%INTRO==BIT ;INTRO LINE ALREADY TYPED
X%EOF==BIT ;EOF PENDING
X%SUPER==BIT ;SUPERCEEDING
X%REEAT==BIT ;TYI SHOULD RETURN LASTCH AGAIN
X%ODD==BIT ;ODD # OF BYTES IN ASCII RECORD
X%UIC==BIT ;TYPFHB SHOULD GIVE UIC
X%VMS==BIT ;VERTICAL MOTION SEEN ON THIS LINE
X%PEOF==BIT ;PREMATURE EOF
X%INT==BIT ;INTERACTIVE OUTPUT DEVICE (DO OUTPUT AFTER CRLF)
X%FF==BIT ;FormFeed WAS SEEN IN THIS LINE
X%SEQ==BIT ;THIS FILE IS A LINE SEQUENCED ASCII TEXT FILE
X%FIR==BIT ;FIRST BLOCK XFER
X%DEX==BIT ;DON'T FOLLOW EXTENSION LINKS ETC
;(USED TO MAKE REDFHB READ 1 FHB ONLY, ETC)
N==P3 ;COPY SCAN'S N AC
U0=16
FP=13 ;FILE POINTER AC
M1=14 ;1ST MASK WORD
M2=15 ;2ND MASK WORD
;N.B.: IT SEEMS LIKE SCAN DOES NOT USE ACS 0, 11 THRU 16, INCLUSIVE
; HERE ARE SOME RANDOM CONSTANTS
;THESE ARE I/O CHANNELS
TTY=10 ; TTY I/O
FIO==15 ; FILE I/O
VIO=16 ; VOLUME I/O
WLD==17 ; WILD'S I/O
.RBSLF==177 ; WORD IN TOPS-10 FILE RIB THAT POINTS TO ITSELF
M.INFH==^D64 ;# OF FILE HEADER BLOCKS (FHBs) IN FIRST CHUNK OF INDEXF.SYS
;NOT SURE, BUT SUSPECT MUST BE GREATER THAN 5.
;ALSO, DUE TO LAZINESS ON OUR PART TO CORRECTLY UPDATE
;THE EQUIVILENT OF THE RETRIEVAL POINTER IN THE FHB FOR
;INDEXF.SYS, YOU REALLY OUGHT TO MAKE THIS NUMBER LARGE ENOUGH
;TO ACCOUNT FOR THE NUMBER OF FILES YOU EXPECT TO HAVE IN
;A NEWLY CREATED FILES-11 VOLUME WHICH IS MANIPULATED BY
;F11 - OF COURSE 20F ITSELF WILL CORRECTLY ADD MORE THAN
;M.INFH FILES AND DO CORRECT UPDATES.
; **** N.B. **** DUE TO DESIGN DEFICIENCIES IN "FELOAD", F11ACP.TSK MUST
; **** **** HAVE AN FHB ALLOCATED IN THE FIRST CHUNK OF INDEXF.SYS
; **** **** OR IT WILL NOT BE ABLE TO FIND F11ACP DURING THE LOAD
OPDEF PJRST [JRST]
VOLMAX=3 ;MAX NUMBER OF CONCURRENTLY DEFINED LOGICAL VOLUMES
SUBTTL DEFINITIONS -- MACROS
; DEFINE THE DEFINE'R MACRO
DEFINE DEFPRE(.a),<.prefix=='.a'
.offset==0>
DEFINE X(.name,.size,.defalt),<
IFNB <.name>,< A.'.name'==<.prefix>
.XCREF A.'.name', S.'.name'>
O.'.name'==.offset
.offset==.offset+^D'.size'
S.'.name'==^D'.size'
IFNB <.defalt>,< M.'.name'==.defalt>
>
SUBTTL TOPS-10 HOME BLOCK
DEFPRE <HOME1>
HOMNAM==0 ;PDP10 WORD #0 HAS 36 BITS OF SIXBIT *HOM*
.OFFSET==HOMNAM*4;FORCE PDP11 POINTER AT HOMNAM
X HSIX,2 ; CONTAIN "SIXBIT" 'HOM'
X HSX0,2 ; CONTAIN 0'S
HOMFE0==61 ;PDP10 WORD#61 HAS 36 BIT POINTER TO FE.SYS (AND VALID BIT)
.offset==HOMFE0*4;FORCE PDP11 POINTER AT HOMFE0
X HLBN,4 ; ADDRESS OF PDP11 FE.SYS FILE
HOMFE1==62 ;PDP10 WORD#62 HAS 36 BIT LENGTH OF FE.SYS
X HLEN,4,^D2048 ;LENGTH OF PDP11 FE.SYS FILE
SUBTTL FILES-11 HOME BLOCK
DEFPRE <H11BUF> ;THESE ALL OFFSET OFF OF H11BUF
X IBSZ,2 ; SIZE OF INDEX-BIT-MAP IN BLOCKS
X IBLH,2 ; DISK LBN ADRRES OF INDEX BIT MAP HIGH WORD
X IBLL,2 ; DISK LBN ADDRESS OF INDEX BIT MAP LOW WORD
X FMAX,2,^O77777 ; MAX # OF FILES ALLOWED ON THIS VOLUME
X SBCL,2,1 ; CLUSTER SIZE FOR STORAGE-BIT-MAP
X DVTY,2 ; DISK-DEVICE TYPE
X VLEV,2 ; STRUCTURE LEVEL
X VNAM,12 ; VOLUME NAME
X ,4 ; RESERVED AREA
X VOWN,2,401 ; VOLUME OWNER'S DECIMAL UIC IN BINARY (IE: [1,1])
X VPRO,2,0 ; VOLUME PROTECTION CODE
X VCHA,2,30 ; VOLUME CHARACTERISTICS (30=NO ATTACH, NO DEVICE CONTROL FCNS)
X DFPR,2,164000 ; DEFAULT PROTECTION FOR FILES
X ,6 ; RESERVED AREA
X WISZ,1,7 ; DEFAULT # OF RETRIEVAL PAIRS IN A WINDOW
X FIEX,1,5 ; DEFAULT # OF BLOCKS TO EXTEND FILES
X LRUC,1,3 ; # ENTRIES IN A DIRECTORY LRU
X ,11 ; "AVAILABLE SPACE"
X CHK1,2 ; CHECKSUM OF WORDS 0-28
X VDAY,2 ; 2 DIGIT DAY OF MONTH
X VMON,3 ; 3 BYTE NAME OF MONTH
X VYER,2 ; 2 DIGIT YEAR IN CENTURY
X ,1 ; ? BLANK PERHAPS?
X VHOR,2 ; 2 DIGIT HOUR IN DAY
X VMIN,2 ; 2 DIGIT MINUTE IN HOUR
X VSEC,2 ; 2 DIGIT SECOND IN MINUTE
X ,398 ;RESERVED FOR RELATIVE VOLUME TABLE
X INDN,12 ;SYSTEM INDEPENDENT VOLUME NAME (12 BLANKS)
X INDO,12 ;SYSTEM INDEPENDENT OWNER NAME ([001,001])
X INDF,12 ;SYSTEM INDEPENDENT FORMAT TYPE ("DECFILE11A")
X ,2 ;NOT USED
X CHK2,2 ;CHECKSUM OF WORDS 0-255.
SUBTTL FILES-11 FILE HEADER BLOCK
DEFPRE <FHBBUF> ;THESE ALL OFFSET OFF OF FHBBUF
X IDOF,1 ; ID AREA OFFSET IN WORDS
X MPOF,1 ; MAP AREA OFFSET IN WORDS
X FNUM,2 ; FILE NUMBER
X FSEQ,2 ; FILE SEQUENCE #
X FLEV,2,401 ; STRUCTURE LEVEL AND SYSTEM NUMBER
X PROG,1 ; PROGRAMMER NUMBER (MEMBER NUMBER)
X PROJ,1 ; PROJECT NUMBER (GROUP NUMBER)
X FPRO,2,164000 ; FILE PROTECTION CODE
X UCHA,1 ; USER CONTROLLER FILE CHARACTERISTICS
UC.CON=200 ; THIS FILE IS "LOGICALLY" (IE: DECLARED) CONTIGUOUS
UC.DLK=100 ; FILE IMPROPERLY CLOSED
X SCHA,1 ; SYSTEM CONTROLLED FILE CHARACTERISTICS
SC.MDL=200 ; FILE MARKED FOR DELETETION
SC.BAD=100 ; BAD BLOCK IN FILE
; ** HERE ARE THE USER FILE ATTRIBUTES
X UFAT,32 ; USER FILE ATTRIBUTES
...==.offset ;;SAVE OFFSET TO THING AFTER UFAT
.offset==O.UFAT ;;GO BACK TO UFAT
X RTYP,1 ; RECORD TYPE BYTE
R.FIX==1 ;TYPE 1 IS FIXED LENGTH
R.VAR==2 ;TYPE 2 IS VARYED LENGTH
R.SEQ==3 ;TYPE 3 IS SEQUENCED RECORDS
X RATT,1 ; RECORD ATTRIBUTE BYTE
FD.FTN==1;IF BIT SET, 1ST DATA BYTE IS CARRIAGE CONTROL
FD.CR==2 ;IF BIT SET, DO "LF" BEFORE LINE DATA,CR AFTER
FD.BLK==10;IF BIT SET, RECORDS CANNOT CROSS BLK BOUNDRYS
X RSIZ,2 ; RECORD SIZE (IF VARYED LENGTH, BIGGEST RECORD IN FILE)
; X HIBK,4 ; HIGH BLOCK; HIGHEST VBN ACTUALLY IN USE
X HIBH,2 ; HIGH BLOCK HIGH
X HIBL,2 ; HIGH BLOCK LOW
; X EFBK,4 ; EOF BLOCK; VBN WHICH IS FIRST NOT IN USE
X EFBH,2 ; EOF BLOCK HIGH
X EFBL,2 ; EOF BLOCK LOW
X FFBY,2 ; FIRST FREE BYTE (IN THE LAST BLOCK)
X RACC,1 ;RECORD ACCESS BYTE
FD.RWM==1;READ$/WRITE$ MODE IF1, 0 MEANS GET$/PUT$
FD.RAN==2;RANDOM ACCESS IF 1, 0 MEANS SEQUENTIAL
FD.PLC==4;LOCATION MODE IF 1, 0 MEANS MOVE MODE
FD.INS==10;PUT$ DOES NOT TRUNCATE IF 1, 0 IT DOES
X RCTL,1 ;DEVICE-CHARACTERISTICS BYTE
FD.REC==1;1 IF RECORD ORIENTED, 0 IF BLOCK ORIENTED (LIKE DISK)
FD.CCL==2;1 IF CARRIAGE CONTROL DEVICE, 0 OTHERWISE
FD.TTY==4;1 IF TELEPRINTER DEVICE
FD.DIR==10;1 IF DIRECTORY DEVICE
FD.SDI==20;1 IF SINGLE DIRECTORY ONLY
FD.SEQ==40;1 IF INHERENTLY SEQUCENTIAL
X CLL,2 ;"CORE LINK LOW" - USED TO LINK FHB SEGMENTS
X CLH,2 ;"CORE LINK HIGH" - USED TO LINK FHB SEGMENTS
.offset==... ;;RESUME NORMAL ALLOCATION
; HERE IS THE ID AREA
M.IDOF==.offset/2 ;COMPUTE OFFSET TO ID AREA
X FNAM,4 ; FILE NAME IN RAD50
X ,2 ; (LAST 3 CHARACTERS OF 9 CHARACTER RAD50 FILE NAME)
.offset==o.fnam
X FNM1,2 ; 1ST WORD OF 3 CONTAINING FILE NAME IN RAD50
X FNM2,2 ; 2ND WORD OF 3 CONTAINING FILE NAME IN RAD50
X FNM3,2 ; 3RD WORD OF 3 CONTAINING FILE NAME IN RAD50
X FTYP,2 ; FILE TYPE IN RAD50
X FVER,2 ; FILE VERSION IN BINARY
X RVNO,2 ; REVISION # IN BINARY
X RVDT,7 ;REVISION DATE
.OFFSET==O.RVDT
X RDAY,2 ; REVISION DATE DAY
X RMON,3 ; REVISION DATE MONTH
X RYER,2 ; REVISION DATE YEAR
X RVTI,6 ;REVISION TIME
.OFFSET==O.RVTI
X RHOR,2 ; REVISION TIME HOUR
X RMIN,2 ; REVISION TIME MINUTE
X RSEC,2 ; REVISION TIME SECOND
X CRDT,7 ;CREATE DATE
.OFFSET==O.CRDT
X CDAY,2 ; CREATION DATE DAY
X CMON,3 ; CREATION DATE MONTH
X CYER,2 ; CREATEION DATE YEAR
X CRTI,6 ;CREATE TIME
.OFFSET==O.CRTI
X CHOR,2 ; CREATION TIME HOUR
X CMIN,2 ; CREATION TIME MINUTE
X CSEC,2 ; CREATION TIME SECOND
X EXDT,7 ;EXPIRATION DATE
.OFFSET==O.EXDT
X XDAY,2 ; EXPIRATION DATE DAY
X XMON,3 ; EXPIRATION DATE MONTH
X XYER,2 ; EXPIRATION DATE YEAR
X ,1 ; USED TO ROUND TO A WORD BOUNDRY
;; MAP AREA
M.MPOF==.offset/2 ;COMPUTE OFFSET TO THE MAP AREA
X ESQN,1 ; EXTENSION SEGMENT NUMBER
X ERVN,1 ; EXTENSION RELATIVE VOLUME NUMBER
X EFNU,2 ; EXTENSION FILE NUMBER
X EFSQ,2 ; EXTENSION FILE SEQUENCE
X CTSZ,1,1 ; SIZE OF THE BLK COUNT FIELD (ALWAYS 1)
X LBSZ,1,3 ; SIZE OF BLOCK NUMBER FIELD (ALWAYS 3)
X USE,1,0 ; # OF RET PNTRS IN USE
X MAX,1,314 ; # OF RET PNTRS SLOTS POSSIBLE
;; RETRIEVAL POINTERS
...==.offset
X RETP,4 ; 4 BYTES OF STUFF FOR EACH RETRIEVAL PAIR
.offset==...
X HRET,1 ; HIGH BYTE OF LBN OF 1ST BLOCK
X RCNT,1 ; # BLKS-1 IN THIS CHUNK
X RLBN,2 ; LOW LBN# OF 1ST BLK IN THIS CHUNK
.offset==776
X CKSM,2 ; CHECKSUM OF WORDS 0 THRU 255.
; THE ABOVE DATA WAS RECONSTRUCTED FROM A SIMPLISTIC APPENDIX OF
; A "WELCOME TO RSX-11M" TYPE MANUAL AND IS LIKELY TO BE
; INCOMPLETE AND INACCURATE TO SOME UNDETERMINED EXTENT.
SUBTTL FILES-11 DIRECTORY ENTRY
DEFPRE <MFDDAT> ;THESE ALL OFFSET OFF OF MFDDAT
X UFNO,2 ; FILE #
X UFSQ,2 ; SEQ #
X UFRV,2 ; ALWAYS (APPARENTLY) 0 ("RELATIVE VOLUME NUMBER")
X UFN1,2 ; 1ST NAME WORD
X UFN2,2 ; 2ND NAME WORD
X UFN3,2 ; 3RD NAME WORD
...==.offset
.offset==o.ufn1
X UFNM,4 ; FILE NAME
X ,2
X UFTY,2 ; FILE TYPE
X UVER,2 ; OCTAL BINARY GENERATION #
.DIROF==.offset ; REMEMBER LENGTH OF DIRECTORY ENTRY
; DETERMINED BY INSPECTION
SUBTTl FILES-11 BIT MAP BUFFER BLOCK
DEFPRE <BMBUF>
X ,3 ; UNUSED
X BCNT,1 ; # OF BLOCKS IN THE SBM
; THESE 2 FIELDS "FLOAT" AND ALWAYS FOLLOW THE LAST USED SAB COUNT WORD
X BDMH,2 ; (THE "INI" UTILITY SETS THIS TO SOMETHING)?
X BDML,2 ; (THE "INI" UTILITY SETS THIS TO SOMETHING)?
X BMXH,2 ; HIGH PART OF LSTLBN COPY
X BMXL,2 ; LOW PART OF LST LBN COPY
; DETERMINED BY INSPECTION
SUBTTL FILE DESCRIPTOR BLOCK
SEARCH SCNMAC
; THESE VALUES ARE STOLEN FROM SCAN, SO THAT WE CAN USE SCAN/WILD
; ROUTINES. NOTE HOWEVER, THAT BECAUSE OF THE "EXTRA" WORDS, WE
; MUST HAVE OUR OWN VERSION OF "FILIN" TO READ A FILE SPEC.
.FXDEV==.FXDEV ;DEVICE NAME, COPIED FROM SCAN
.FXNAM==.FXNAM ;FILE NAME, COPIED FROM SCAN
.FXNMM==.FXNMM ;FILE NAME MASK
.FXEXT==.FXEXT ;FILE-NAME-EXTENSION,,EXTENSION-MASK (MASK NON0 IF .)
.FXMOD==.FXMOD ;MODIFIED WORD
.FXMOM==.FXMOM ;MODIFIER MASK
.FXDIR==.FXDIR ;DIRECTORY WORD (EACH HALF =0 IF DEFAULT;SFD:0 IF END)
.FXDIM==.FXDIM ;DIRECTORY MASK
.FXLND==.FXLND ;LENGTH OF "DIRECTORY SPECIFICATION"
.FXBFR==.FXBFR ;/BEFORE VALUE
.FXSNC==.FXSNC ;/SINCE
.FXABF==.FXABF ;/ABEFORE
.FXASN==.FXASN ;/ASINCE
.FXFLI==.FXFLI ;FILE MINIMUM SIZE, IN WORDS
.FXFLM==.FXFLM ;FILE MAXIMUM SIZE, IN WORDS
.FXEST==.FXEST ;/ESTIMATE
.FXVER==.FXVER ;/VERSION
DEFINE FX(.NAME),<'.NAME'==.FXLEN
.FXLEN==.FXLEN+1>
.FXLEN==.FXVER+1 ;COMPUTE SIZE OF FILE SPEC BLOCK
FX .F2NAM ;ADD ANOTHER WORD, 2ND PART OF FILE NAME
FX .F2NMM ;ADD ANOTHER WORD, 2ND PART OF FILE NAME MASK
FX .FXNUM ;FILE # OF FILE NXTFDB FOUND
FX .FXFLG ;FLAGS ASSOCIATED WITH THAT FILE
FX .FXGEN ;"GENERATION" NUMBER OF FILE
FX .FXSEQ ;SEQ# OF FILE
FX .FXSWT ;SWITCHES APPLIED TO THIS FILE SPEC
FX .FXLNK ;POINTER TO NEXT FILE SPEC IN THIS CHAIN
FX .FXDIN ;FIRST PART OF FILES-11 DIRECTORY NAME
FX .F2DIN ;SECOND PART
FX .FXDNM ;FIRST PART OF DIRECTORY NAME MASK
FX .F2DNM ;SECOND PART
FX .FXRVN ;RELATIVE VOLUME NUMBER
;HERE ARE BITS, BYTES, AND FIELDS IN THE MODIFIER WORD
FX.NDV==FX.NDV ;SET IF NULL DEVICE
FX.NUL==FX.NUL ;NULL EXTENSION
FX.DIR==FX.DIR ;DIRECTORY SPECIFIED (MOD=0 IF [-])
FX.PHY==FX.PHY ;/PHYSICAL
FX.NOM==FX.NOM ;/OKNONE
FX.DFX==FX.DFX ;DIRECTORY DOES NOT NEED FIX-UP BY WILD
FX.TRM==FX.TRM ;FIELD, CODE FOR FILE SPEC'S TERMINATING CHARACTER
.FXTRA==.FXTRA ;& (AND)
.FXTRO==.FXTRO ;! (OR)
.FXTRN==.FXTRN ;- (NOT)
.FXTRC==.FXTRC ;+ (CONCATENATE)
FX.STR==FX.STR ;/STRS
FX.PRT==FX.PRT ;/OKPROT
FX.SUP==FX.SUP ;/ERSUPERSEDE
;N.B.: IT LOOKS AS IF BITS 12 THRU 20 ARE FREE, BUT DON'T BET ON IT
FX.DEN==FX.DEN ;/DENSITY, 3 BIT FIELD
FX.PAR==FX.PAR ;/PARITY, 1 BIT FIELD
FX.PRO==FX.PRO ;/PROTECTION OR <NNN>, 9 BIT FIELD
FX.NUN==1B12 ;SET IF NO NAME WAS EVER SPECIFIED
FX.EQL==1B13 ;SET IF THIS SPEC ENDED WITH =
FX.CMA==1B14 ;SET IF THIS SPEC ENDED WITH ,
; DEFINE THE FILE SWITCHES
DEFINE SS,<
S FILENO,FILEIN ;/FILENUMBER:number
S CHARAC,CHAIN ;/CHARACTERISTICS:{ATCH:DCF}
S CONTIG
S IMAGE ;/IMAGE
S BINARY ;/BINARY
S ASCII ;/ASCII
S SIZE,SIZIN ;/SIZE:nnn
S MAXFIL,MAXFIN ;/MAXFIL:nnn
S FULL ;/FULL
S INDEX,IDXIN ;/INDEX:{BEG,MID,END,BLK:nnn}
S DETAIL ;/DETAILS
S ALLOCA,ALCIN ;/ALLOCATE:nnnn
S VPROTE,VPRTIN ;/VPPROTECTION:<RWED,R...>
S FPROTE,FPRTIN ;/FPROTECTION:<RWED,R...>
S EXTEND,EXTDIN
S DOTS ;/DOTS - give got every time ENTER for FE.SYS fails
S NOVM ;/NOVM - do not copy motion characters CR,LF
;(BUT they are still implied if record type says so)
S NOCHEC ;/NOCHECK - don't disallow this command
>
DEFINE S(.name,.serve),<FX V$'.name'>
SS ;BUILD THE SWITCH SECTION OF THE FDB
DEFINE TYPE(.text,adr),<
PUSHJ P,[PUSHJ P,TYPE..
CAI [ASCIZ ~'.TEXT'~]
IFB <ADR>,<POPJ P,0>
IFNB <ADR>,<POP P,(P)
JRST ADR>]
>
DEFINE ERROR(.text,.adr<.ERR>),<
JRST [RELEAS TTY,
OUTSTR [ASCIZ ~? '.text'
~]
JRST '.adr']>
; DEFINE THE PDP11 RAD50 CHARACTER SET
DEFINE RDEF(.START,.STRING),<.FOO==.START-1
IRPC .STRING,<$R.'.STRING'==<.FOO==<.FOO+1>>>>
$R.==0 ;BLANK MUST BE DONE THIS WAY
RDEF 1,<ABCDEFGHIJKLMNOPQRSTUVWXYZ>
RDEF 33,<$.>
RDEF 36,<0123456789>
; MACRO TO MOVE 1 PDP11 FORMATTED FIELD TO ANOTHER (LEFT TO RIGHT)
DEFINE MOV.(.ORIGIN,.DESTINATION,.OFFSET<[0]>),<
PUSHJ P,[JSP U0,MOV..
CAI .ORIGIN ;;POINT AT ORIGIN DATA
CAI A.'.DESTINATION';;POINT AT DESTINATION STRUCTURE
CAI O.'.DESTINATION';;SPECIFY OFFSET FROM DESTINATION
CAI S.'.DESTINATION';;SPECIFY # OF BYTES TO MOVE
CAI .OFFSET ;;POINT AT POSSIBLE ADDITIONAL OFFSET
POPJ P,0]>
; MACRO TO MOVE 1 PDP10 FORMATTED FIELD TO A PDP11 FIELD (4 BYTES MAX)
DEFINE STOR.(.ORIGIN,.DESTINATION,.OFFSET<[0]>),<
PUSHJ P,[JSP U0,STOR..
CAI .ORIGIN ;;POINT AT ORIGIN PDP10 DATA
CAI A.'.DESTINATION';;POINT AT DESTINATION FIELD
CAI O.'.DESTINATION';;GIVE BYTE OFFSET FROM DESTINATION
CAI S.'.DESTINATION';;#BYTES IN DESTINATION FIELD
CAI .OFFSET ;;ADDRESS OF ADDITIONAL OFFSET
POPJ P,0]>
; MACRO TO MOVE 1 PDP11 FORMATTED FIELD TO A PDP10 FIELD (4 BYTES MAX)
DEFINE LOAD.(.ORIGIN,.DESTINATION,.OFFSET<[0]>),<
PUSHJ P,[JSP U0,LOAD..
CAI .ORIGIN ;;POINT AT DESTINATION PDP10 FIELD
CAI A.'.DESTIN' ;;POINT AT ORIGIN PDP11 FIELD
CAI O.'.DESTIN' ;;BYTEOFFSET FROM PDP11 FIELD
CAI S.'.DESTIN' ;;#BYTES IN PDP11 FIELD
CAI .OFFSET ;;ADDRESS OF ADDITIONAL OFFSET
POPJ P,0]>
; MACRO TO GENERATE PDP11 WORD STRINGS OF PDP11 RAD50 CHARACTERS
DEFINE .RAD50(S),<
COUNT==0
IRPC S,<COUNT==COUNT+1> ;;FIRST COMPUTE TOTAL # CHARACTERS
WORDS==COUNT/3 ;;WORDS=# PDP11 WORDS GENERATED
REMAIN==COUNT-<WORDS*3> ;;REMAIN=REMAINDER FROM COUNT/3
IFN REMAIN,<WORDS==WORDS+1> ;;ACCOUNT FOR NON-ZERO REMAINDER
PAIRS==WORDS/2 ;;PAIRS=# PDP11 WORD PAIRS
;;(IE: # OF PDP10 WORDS NEEDED)
IFN WORDS&1,<PAIRS==PAIRS+1> ;;IF ODD WORDS, ONE MORE PAIR NEEDED
C==0 ;; CURRENT CHARACTER POSITION = 1ST CHAR IN STR
REPEAT PAIRS,< ;; FOR I=1 TO (#PDP10.WORDS.REQUIRED)
TWV==0 ;; TWO-WORD-VALUE=0
REPEAT 2,< ;; FOR J=1 TO 2 (TO GET BOTH PDP11 WORDS)
RAD3(<S>,C,OWV) ;; GO GET 1 WORD OF 3 RAD50 CHARACTERS
TWV==TWV_^D18 ;; MAKE ROOM BY PUTTING OLD IN LH
TWV==TWV+OWV ;; ADD IN NEXT 3 CHARACTERS
C==C+3 ;; POSITION TO GET NEXT 3 CHARACTERS
> ;; LOOP TO GET BOTH PDP11 WORDS
EXP TWV ;; DUMP OUT TWO PDP11 WORDS (INTO 1 PDP10 WORD)
> ;;END REPEAT PAIRS ;; NEXT I (LOOP FOR ALL PDP10 WORDS NEEDED)
>;;END DEFINE .RAD50
;; MACRO TO EXTRACT 3 .RAD50 CHARACTERS FROM A STRING ARGUMENT
DEFINE RAD3(S,C,OWV),<
OWV==0 ;; ONE-WORD-VARIABLE STARTS OFF = 0
RC==0 ;; # OF RETURNED CHARACTERS = 0
CC==0 ;; CURRENT CHARACTER POSITION = 0
IRPC S,<
IFL RC-3,<IFGE CC-C,<OWV==OWV*50+$R.'S'
RC==RC+1>>
CC==CC+1>
REPEAT 3-RC,<OWV==OWV*50>;;LEFT JUSTIFY IT
>
;; MACRO TO GENERATE PDP11 .ASCII STRINGS
DEFINE .ASCII(S),<
COUNT==0 ;; COUNT OF CHARACTERS TOTAL = 0
IRPC S,<COUNT==COUNT+1> ;; COUNT THE NUMBER OF CHARACTERS IN STRING
WORDS==COUNT/2 ;; COMPUTE # OF PDP11 WORDS
IFN COUNT&1,<WORDS==WORDS+1>;; ACCOUNT FOR POSSIBLE TRAILING BYTE
PAIRS==WORDS/2 ;; COMPUTE # OF PDP10 WORDS (PAIRS OF PDP11 WDS)
IFN WORDS&1,<PAIRS==PAIRS+1>;; ACCOUNT FOR POSSIBLE TRAILING PDP11 WORD
C==0 ;; START AT FIRST CHARACTER
REPEAT PAIRS,< ;; FOR I = 1 TO (#PDP10.WORDS.NEEDED)
TWV==0
REPEAT 2,< ;; FOR J= 1 TO 2 (ONCE FOR EACH HALF OF PDP10)
ASC2(S,C,OWV) ;; GO GET 2 MORE BYTES
TWV==TWV_^D18 ;; PUT PREVIOUS IN LH
TWV==TWV+OWV ;; MERGE IN CURRENT 2 BYTES
C==C+2 ;; ADVANCE PAST 2 MORE BYTES
>;;END REPEAT 2 ;; NEXT J
EXP TWV ;; DUMP OUT 4 ACCUMLATED BYTES
>;;END REPEAT PAIRS
>;;END DEFINE .ASCII
; MACRO TO EXTRACT (UP TO ) 2 ASCII BYTES FROM A LONG STRING
DEFINE ASC2(S,C,OWV),<
CC==0 ;;CURRENT CHARACTER POSITION
RC==0 ;;# OF RETURNED CHARACTERS (IE: 0,1, OR 2)
OWV==0 ;;16 BIT VALUE OF RETURNED CHARACTERS
IRPC S,<IFL RC-2,<IFGE CC-C,<
IFE RC,<OWV=="S"> ;;RETURN 1ST CHAR IN "RH"
IFN RC,<OWV==OWV+<"S"_^D8>>;;RETURN 2ND IN "LH"
RC==RC+1>>
CC==CC+1>
>
SUBTTL CODE
F11: TDZA T1,T1 ;SET T1=0 FOR NORMAL ENTRY
SETO T1, ;SET T1=-1 FOR CCL ENTRY
MOVEM T1,CCLFLG ;INITIALIZE A FLAG TO REMEMBER
RESET ;
MOVE P,[IOWD PLEN,PSTAK] ;INIT THE STACK POINTER
SETZ F, ;INIT THE FLAGS
PUSHJ P,IMPURE ;GO INITIALIZE NECESSARY IMPURE DATA
PROMPT: RELEAS TTY, ;FORCE FINAL STUFF OUT
RESET ;FORGET FILES, ETC
HLRZ T1,.JBSA## ;GET ORIGINAL SIZE
CORE T1, ;RESTORE ORIGINAL SIZE
JFCL ;IGNORE IT
MOVE P,[IOWD PLEN,PSTAK] ;INIT THE STACK
EXCH T1,LASTCH ;GET LAST CHARACTER
CAIN T1,32 ;SKIP IF NOT ^Z
EXIT 1, ;DO A SOFT EXIT IF ^Z SEEN
SETZ F, ;INIT FLAGS
SKPINL ;CLEAR ^O IF ANY
JFCL ;IGNORE LIKELY NONSKIP RETURN
SETZM BUF111 ;INDEXF NOT IN CORE
;< MATCH BRAKET IN LINE BELOW
OUTSTR [ASCIZ .F11> .] ;PROMPT FOR INPUT
PUSHJ P,SIXIN ;READ A POSSIBLE COMMAND VERB
PUSHJ P,TRMSKP ;SKIP IFF END OF LINE AFTER VERB
TDOA F,[X%REEAT] ;REEAT TERMINATOR
JUMPE T1,.ERR ;REPROMPT ON BLANK LINES
PUSHJ P,FNDIDX ;FIND INDEX OF COMMAND FROM TABLE
CAI CMDSIX ;...USE SIXBIT TABLE "CMDSIX"
SKIPGE T1 ;SKIP IF VALID COMMAND KEYWORD
ILLCMD: ERROR <Illegal syntax> ;CATCH ALL ERROR MESG
HRRZM T1,CMDIDX ;SAVE THE COMMAND INDEX FOR LATER
PUSHJ P,DOGETS ;GO DO UP-TO-THE-MINUTE GETTABs
HRRZ T1,CMDIDX ;GET INDEX OF COMMAND
PUSHJ P,@CMDADR(T1) ;GO EXECUTE THE COMMAND
.ERR: PUSHJ P,SKEOL ;GET RID OF INPUT IF ANY LEFT
JRST PROMPT ;AND LOOP FOR ANOTHER COMMAND
SUBTTL COMMANDS
DEFINE CC,<
C ASSIGN,<
ASSIGN (no arguments)
List all currently assigned logical volume names.
ASSIGN vol:=
Forget logical volume name.
ASSIGN vol:=str:file.ext[path]
Create a logical volume.
Logical volumes cannot be used in INI or DESTROY commands.
>
C BOOT,<
BOOT vol:=str:file.ext[path]
Copy the .BIN formatted input file onto the boot area of the volume.
>
C DELETE,<
DELETE vol:file.typ;gen[uic]{,vol:file.typ;gen[uic],...}
Delete a FILES-11 file.
"Vol:" must be explicit.
All other fields default to "*".
N.B.: DELETE VOL: is the same as DELETE VOL:*.*;*[*,*]
/FILE:<file number> delete file # from IBM, but don't try
to deallocate FHB storage and don't try
to fixup owning directory
>
C DESTRO,<
DESTROY str:{,str:,str:,str:}
Destroy the FILES-11 volume (if any) on the specified MOUNTed
TOPS-10 file structure. "str:FE.SYS[1,4]" is deleted and the home
blocks on "str:" are rewritten to remove the pointers to FE.SYS.
>
C DIRECT,<
DIRECT {log file=}vol:file.typ;gen[uic]{,vol:file.typ;gen[uic],...}
Give a "directory" ordered directory of a FILES-11 volume.
List the FHB information for every file matching the FILES-11 file spec.
Choose only files found in the system directory files.
If "log file" is missing, the default is TTY:.
"Vol:" must be explicit.
All other missing components default to "*".
/DETAILS list attribute and mapping information as well
>
C EXIT,<
EXIT
Exits from F11.
>
C GET,<
GET {str:file.ext[p,pn]=}vol:file.typ;generation[uic]
Copy files from the FILES-11 volume to the specified TOPS-10 structure.
If "str:" is missing, DSK: is the default.
If "[p,pn]" is missing, [-] is the default.
"vol:" must be explicit.
All other missing components default to "*".
/IMAGE don't do data conversion
/ASCII convert from PDP11 variable length ASCII
(Generally speaking, a reasonable /IMAGE or /ASCII will
be defaulted if both are omitted)
>
C HELP,<
HELP
Lists out brief list of commands.
>
C INDEX,<
INDEX {log file=}str:{,str:,str:,str:,...}
Give an "index" ordered directory of a FILES-11 volume.
List the FHB information for every file on the structure.
Choose files from the Index-bit-map rather than the directory files.
If "log file" is missing, the default is TTY:.
/DETAILS list attribute and mapping information as well
>
C INI,<
INI str:{volumelabel}{[owner's UIC]}
Create and initialize a FILES-11 volume on the MOUNTed TOPS10 str:.
str: must be explicit.
volumelabel is optional and defaults to blank.
[owner's UIC] is optional and defaults to [1,1].
/CHARACTERISTIC:ATTACH allow 20F task to attach to volume.
/CHARACTERISTIC:DCFUNC allow 20F device control functions.
/EXTEND:<increment of disk blocks during extend operations>
(Default 5, minimum 1, maximum 127)
/FPROTECTION:[default file protection for files on this volume]
(Default is <RWED,RWED,RWE,R>)
(/FPROTECTION can be given with <RWED,...> notation,
without giving a /FPROTECTION switch)
/FULL allocate entire disk to RSX20F volume
(N.B.: TOPS10 structures is destroyed!!)
/INDEX:BEG allocate INDEXF.SYS near block 0 if possible
/INDEX:BLK:nnn allocate INDEXF.SYS near block "nnn" if possible
/INDEX:END allocate INDEXF.SYS on highest block possible
/INDEX:MID allocate INDEXF.SYS near mid point of volume
/MAXFIL:<maximum allowed # of files on volume>
(default 65535, minimum 5, maximum 65535)
/SIZE:<number of disk blocks to allocate to FILES-11 volume>
(Default 2048, minimum about 150, no maximum)
/VPROTECTION:<protection applied to the volume>
(Default is <,,,>)
>
C PATH,<
PATH vol:[uic]
Setup defaults for "vol:" and "[uic]"; default default is vol:[*,*].
>
C PUT,<
PUT vol:file.typ;gen[uic]=str:file.ext[path]{,str:file.ext[path],...}
Copy file(s) onto the front end area from the TOPS10 file system.
"Vol:" must be explicit.
"[uic]" must be explicit, but can be defaulted from PATH command.
"[path]" defaults to [-].
";gen" defaults to the "first free" gen number above the highest used.
"str:" defaults to DSK:.
All other missing fields default to "*".
/FILE:n use file number "n" on output
/IMAGE don't do any data conversion
/ASCII convert to PDP11 varible length ASCII records
/CONTIG set the "contiguous" bit in the FHB
(Generally speaking, reasonable /IMAGE/ASCII/CONTIG switches
will be defaulted if all are omitted)
>
C UFD,<
UFD str:[uic]{,str:[uic],str:[uic...}
Create a file directory for the specified UIC on the specified volume.
str: is the TOPS10 name of the FILES-11 volume and must be explicit.
[uic] must be explicit.
The protection may be specified either via <RWED,...> or /FPROTECTION.
/ALLOCATE:<preallocate space for this many files, default=32>
/FPROTECTION:<protection to be given to the directory file>
>
C VOLUME,<
VOLUME {log file=}str:{,str:,str:,str:,...}
List some FILES-11 volume statistics to the TOPS10 log file.
"str:" must be a MOUNTed TOPS-10 file structure.
str: must be explicit.
If "log file" is missing, the default is "TTY:".
>
>
; CREATE A BUNCH OF TABLES INDEXED BY COMMAND VERB'S INDEX
DEFINE C(.a1,.a2),<SIXBIT @'.a1'@>;BUILD SIXBIT TABLE OF COMMAND VERBS
XLIST
CMDSIX: CC
0
LIST
DEFINE C(.a1,.a2),<EXP C$'.a1'>;BUILD ADDRESS TABLE OF COMMAND DISPATCHS
XLIST
CMDADR: CC
LIST
DEFINE C(.a1,.a2),<EXP T$'.a1'>;CREATE TABLE OF HELP TEXT POINTERS
XLIST
CMDTXT: CC
LIST
DEFINE c(.a1,.a2),<T$'.a1':ASCIZ @'.a2'@>;CREATE HELP TEXTS
XLIST
CC
LIST
SUBTTL COMMANDS -- ASSIGN
; THE ASSIGN COMMAND ALLOWS THE USER TO CREATE A "LOGICAL VOLUME".
; BY REFERRING TO A LOGICAL VOLUME NAME, THE USER CAN ACCESS A
; "FE.SYS" TYPE FILE WHICH NEED NOT RESIDE ON ANY TYPE OF DISK
; BLOCK NUMBER BOUNDRY, ETC. THUS, YOU CAN USE ORDINARY PIP COPY
; COMMANDS TO KEEP AN FE.SYS SOMEWHERE AND STILL BE ABLE TO ACCESS IT.
C$ASSI: PUSHJ P,FILIN ;READ IN A FILE LIST
SKIPN FP,IPLIST ;SKIP IF A LIST WAS GIVEN
JRST C$VLSA ;LIST ALL OF THEM
SKIPN .FXNAM(FP) ;MUST NOT BE A FILE NAME
SKIPE .F2NAM(FP) ;...
JRST ILLCMD ;COMPLAIN IF FILE NAME
SKIPE .FXDEV(FP) ;MUST BE A VOLUME NAME
SKIPE .FXDIR(FP) ;MUST NOT BE A DIRECTORY
JRST ILLCMD ;COMPLAIN
MOVE T1,[FX.EQL] ;
TDNN T1,.FXMOD(FP) ;MUST BE AN =
JRST C$VLST ;GO DO A LIST COMMAND
HRRZ FP,.FXLNK(FP) ;ADVANCE TO FILE SPEC AFTER =
JUMPE FP,C$VCLR ;BRANCH IF "CLEAR" REQUEST
HRRZ FP,.FXLNK(FP) ;ADVANCE TO NEXT SPE
JUMPN FP,ILLCMD ;MUST BE 2 AND ONLY 2 SPEX
PJRST C$ASS1 ;GO DO ASSIGN
; HERE TO CLEAR AN ASSIGNED LOGICAL VOLUME NAME
C$VCLR: PUSHJ P,SAVE1
MOVSI P1,-VOLMAX ;MAX # OF ENTRIES
HRRZ FP,IPLIST ;LOAD PTR TO 1ST SPEC
MOVE T1,.FXDEV(FP) ;LOAD VOLUME NAME
SKIPN T2,VOLTBL(P1) ;GET IT'S VOLUME NAME
C$CLR2: AOBJN P1,.-1 ;DO THEM ALL
JUMPG P1,[ERROR <Volume not found>]
CAME T2,.FXDEV(FP) ;IS THIS IT?
JRST C$CLR2 ;BRANCH IF NO MATCH, TRY NEXT NAME
MOVE FP,VOLPTR(P1) ;GET POINTER
PUSH P,VOLTBL(P1) ;SAVE NAME
SETZM VOLTBL(P1) ;ZERO NAME SO WE FORGET IT
TYPE <Deleted: >
POP P,T1 ;GET BACK THE DELETED NAME
PUSHJ P,SIXOUT ;TYPE NAME OF DELETED VOLUEM
TYPE <:=> ;PRETTY STUFF
PUSHJ P,TYPFDB ;TYPE USER'S FILE SPEC
PJRST CRLF
; HERE TO LIST ALL LOGICAL VOLUMES
C$VLSA: PUSHJ P,SAVE1
MOVSI P1,-VOLMAX
C$VLA1: MOVE FP,VOLPTR(P1) ;GET POINTER TO THE FDB
SKIPE VOLTBL(P1) ;SKIP IF NOT USED
PUSHJ P,C$VLS0 ;JOIN COMMON CODE TO TYPE ONE DEF
AOBJN P1,C$VLA1 ;LOOP FOR ALL
POPJ P,
; HERE TO LIST A LOGICAL VOLUME
C$VLST: PUSHJ P,SAVE1
MOVSI P1,-VOLMAX
C$VLS1: MOVE T1,VOLPTR(P1) ;GET FDB POINTER
CAME T1,.FXDEV(FP) ;SKIP IF WE FOUND A MATCH
AOBJN P1,C$VLS1 ;KEEP TYRING
JUMPGE P1,[ERROR <No matching volume name>]
MOVE FP,T1 ;COPY FDB POINTER
C$VLS0: MOVE T1,VOLTBL(P1) ;GET NAME
PUSHJ P,SIXOUT ;TYPE VOLUME NAME
TYPE <:=>
PUSHJ P,TYPFDB ;TYPE FILE SPEC FOR VOLUME
MOVE T1,[S$IMAGE] ;GET THE /IMAGE MODE BIT
TDNE T1,.FXSWT(FP) ;SKIP IF NOT /IMAGE MODE
TYPE </IMAGE>
PJRST CRLF
; HERE TO CREATE A LOGICAL VOLUME NAME
C$ASS1: HRRZ FP,IPLIST ;SET FP=1ST SPEC
MOVE T1,.FXDEV(FP) ;GET VOLUME NAME
MOVSI P1,-VOLMAX
CAME T1,VOLTBL(P1) ;SKIP IF VOLUME ALREADY EXISTS
AOBJN P1,.-1 ;BRANCH IF MORE VOLUMES TO CHECK
JUMPLE P1,C$ASS2 ;BRANCH IF VOLUME ALREADY EXISTS
MOVSI P1,-VOLMAX
SKIPE VOLTBL(P1) ;SKIP IF VOLUME ENTRY FREE
AOBJN P1,.-1 ;BRANCH IF MORE ENTRIES TO CHECK
JUMPG P1,[ERROR <Volume table full>]
C$ASS2: MOVEM T1,VOLTBL(P1) ;INSERT LOGICAL NAME
HRRZ FP,.FXLNK(FP) ;STEP FP TO FILE NAME
MOVEI T1,(FP) ;POINT AT FILE SPEC BLOCK
MOVEI T2,OPNBLK ;POINT TO TOPS-10 OPEN/INIT BLOCK
MOVEI T3,LERBLK ;POINT AT LOOKUP/RENAME/ENTER BLOCK
MOVEI T4,PTHBLK ;POINT AT TOPS-10 PATH. BLOCK
PUSHJ P,.STOPB## ;CALL SCAN TO EXPAND FILE SPEC BLOCKS
ERROR <Can't "setup" logical volume file name/path>
MOVEI T1,.IODMP ;.IODMP IS TOPS-10 DUMP MODE
MOVEM T1,OPNBLK ;FIXUP THE OPEN/INIT BLOCK
OPEN FIO,OPNBLK ;ATTEMPT ACCESS TO HIS SPECIFIED DEVICE
ERROR <Can't OPEN logical volume device>
MOVEI T1,.RBSPL ;SETUP "LENGTH" WORD FOR LOOKUP BLOCK
MOVEM T1,LERBLK+.RBCNT ;...INTO THE LOOKUP BLOCK
LOOKUP FIO,LERBLK ;ATTEMPT ACCESS TO HIS SPECIFIED FILE
ERROR <Can't LOOKUP logical volume file>
MOVSI T1,(FP) ;GET POINTER = TEMP_FDB_ADR,,0
HRR T1,VOLPTR(P1) ;INSERT POINTER=TEMP_FDB_ADR,,PERM_ADR
MOVEI T2,.FXLEN(T1) ;CALCULATE T2=LAST ADR IN PERM_FDB
BLT T1,-1(T2) ;COPY TEMP FDB TO PERM FDB FOR THIS VOL
MOVE T1,VOLTBL(P1) ;GET HIS SPECIFIED VOLUME NAME
PUSHJ P,SIXOUT ;TYPE HIS SPECIFIED VOLUME NAME
TYPE <:=> ;...
PUSHJ P,TYPFIO ;TYPE REAL INFO
MOVE T1,[S$IMAGE]
TDNE T1,.FXSWT(FP)
TYPE </IMAGE>
PUSHJ P,CRLF
RELEAS FIO, ;DROP CONNECTION TO VOLUME FILE
POPJ P, ;DONE
SUBTTL COMMANDS -- BOOT
; "BOOT" READS A PDP11 .BIN FORMATTED FILE.
; IT CONSTRUCTS AN INCORE IMAGE OF WHAT THE PDP11 WOULD HAVE.
; IT WRITES THAT IMAGE TO DISK TO ABSOLUTE BLOCK NUMBERS IN 1:1 STYLE.
; IE: PDP11 ADDRESS 0 GOES TO BLOCK 0 WORD 0, ADDRESS 1000 GOES
; TO BLOCK 1 WORD 0, ETC. USED TO PUT "FELOAD" (IN PARTICULAR) ONTO
; BLOCKS 0 THRU 3 WHICH ARE STILL (APPARENTLY) NOT USED BY TOPS-10.
C$BOOT: PUSHJ P,FILIN ;READ IN A FILE LIST
SKIPN FP,IPLIST ;SKIP IF A LIST GIVEN
JRST ILLCMD ;
SKIPN .FXNAM(FP) ;SKIP IF OUTPUT FILE NAME GIVEN
SKIPE .F2NAM(FP) ;SKIP IF OUTPUT FILE NAME NOT GIVEN
JRST ILLCMD ;COMPLAIN IF OUTPUT FILE NAME GIVEN
SKIPE .FXDIR(FP) ;SKIP IF OUTPUT PATH NOT GIVEN
JRST ILLCMD ;COMPLAIN IF OUTPUT PATH GIVEN
MOVE T1,[FX.EQL] ;GET THE "EQUAL SEEN" BIT
TDNN T1,.FXMOD(FP) ;MUST BE = SIGN IN OUTPUT SPEC
JRST ILLCMD ;COMPLAIN IF NO = SEEN AFTER OUTPUT SPEC
HRRZ FP,.FXLNK(FP) ;GET LINK TO NEXT FILE
JUMPE FP,ILLCMD ;COMPLAIN IF NO FILE AFTER THE =
HRRZ FP,.FXLNK(FP) ;GET LINK TO NEXT FILE
JUMPN FP,ILLCMD ;COMPLAIN IF THERE IS MORE THAN 1 INPUT
PUSHJ P,SAVFF ;SAVE CORE BOUNDS
PJRST C$BOT1 ;GO DO BOOT
; SETUP THE OUTPUT FILE (IE: THE VOLUME)
C$BOT1: HRRZ FP,IPLIST ;LOAD FP TO POINT AT VOLUME NAME
PUSHJ P,OPNVIO ;OPEN FOR I/O
SKIPE FAKVOL ;SKIP IF VOLUME IS REAL
ERROR <Can't put boot on logical volume>
; SETUP THE INPUT FILE, THE .BIN FORMATTED FILE
HRRZ FP,.FXLNK(FP) ;POINT AT INPUT FILE
MOVEI T1,(FP) ;POINT AT FILE SPEC BLOCK
MOVEI T2,OPNBLK ;POINT AT OPEN DEVICE BLOCK
MOVEI T3,LERBLK ;POINT AT LOOKUP BLOCK
MOVEI T4,PTHBLK ;POINT AT PATH BLOCK
PUSHJ P,.STOPB## ;SET ALL UUO BLOCKS
ERROR <Cannot setup input files>
MOVE T1,[.IODMP] ;DUMP MODE
MOVEM T1,OPNBLK+0 ;SET IT
SETZM OPNBLK+2 ;NO BUFFERS
OPEN FIO,OPNBLK ;OPEN IT
ERROR <Cannot OPEN input device>
MOVEI T1,.RBVER ;GET T1=SIZE OF LOOKUP BLOCK
MOVEM T1,LERBLK+.RBCNT ;SETUP LOOKUP BLOCK SIZE
LOOKUP FIO,LERBLK ;FIND INPUT FILE
ERROR <Cannot find input file>
; SHARP OBSERVERS WILL NOTE A SIMILARITY TO THE LOAD .BIN FILE CODE
; UPON KLDCP, UPON WHICH THIS CODE WAS LIGHTLY BASED
SETZM BOTCNT ;
SETZM BOTPTR ;
SETZM LASTHI
; LOAD A "CHUNK" OF PDP11 BINARY CODE
LDBINY: SETZM CHKVAL ;INIT CHECKSUM FOR THIS RECORD
PUSHJ P,G10BYT ;GET PDP11 BYTE FROM PDP10 FILE
SOJN T1,LDBINY ;IGNORE EVERYTHING TILL WE FIND A "1"
PUSHJ P,G10BYT ;IGNORE BYTE FOLLOWING THE "1"
PUSHJ P,G10WRD ;GET PDP11 WORD FROM PDP10 FILE
SUBI T1,6 ;SUBTRACT 6 FROM THIS WORD COUNT
JUMPE T1,LJMP ;IF WC=6, THEN THIS IS AN XFER RECORD
MOVEM T1,LBC ;SAVE COUNT OF REMAINING DATA
PUSHJ P,G10WRD ;GET PDP11 WORD, LOAD ADDRESS
MOVE P1,T1 ;SAVE P1=LOAD ADDRESS
CAIL P1,BOTBLK*200*4 ;SKIP IF IN RANGE
ERROR <Address in .BIN file is out of range>
PUSHJ P,TELHGH ;MENTION PREVIOUS HIGH
TYPE <Loading >
MOVE T1,P1 ;GET BACK THE LOAD ADDRESS
PUSHJ P,OCTOUT ;TYPE THE LOAD ADDRESS
LDBIN2: PUSHJ P,G10BYT ;GET A BYTE
SOS T2,LBC ;ADJUST BYTE COUNT TO ACCOUNT FOR IT
JUMPGE T2,LDBIN3 ;BRANCH IF THAT WAS NOT LAST BYTE
SKIPE CHKVAL ;SKIP IF CHECKSUM ENDED UP 0S
error <Checksum error while reading .BIN file>
JRSt LDBINY ;GO IF CHECKSUM WAS OK
LDBIN3: MOVE P2,P1 ;COPY ADDRESS OF BYTE
IDIVI P2,4 ;CONVERT TO PDP10 WORD IN P2, BYTEIN P3
DPB T1,[POINT 8,BOTBUF(P2),17 ; 0
POINT 8,BOTBUF(P2),9 ; 1
POINT 8,BOTBUF(P2),35 ; 2
POINT 8,BOTBUF(P2),27](P3) ; 3
MOVEM P1,LASTHI ;REMEMBER HIGHEST ADDRESS SO FAR
CAML P1,HIHIGH ;SKIP IF NOT ABSOLUTE HIGHEST SO FAR
MOVEM P1,HIHIGH ;REMEMBER ABSOLUTE HIGHEST
AOJA P1,LDBIN2 ;LOOP BACK TO LOAD MORE BYTES
; HERE WHEN ALL DONE
LJMP: PUSHJ P,TELHGH ;MENTION HIGHEST ADDR EVER LOADED
PUSHj P,G10WRD ;GO GET POSSIBLE XFER ADDRESS
PUSH P,T1 ;SAVE WHAT MAY BE XFER ADDR
PUSHJ P,G10BYT ;GET NEXT BYTE
SKIPE CHKVAL ;MAKE SURE WE ENDED UP WITHOUT ERROR
ERROR <checksum error at ljmp>
POP P,T1 ;RESTORE XFER ADDR
TYPE <
Xfer address = >
PUSHJ P,OCTOUT ;TYPE XFER ADDR
TYPE <
Highest address loaded = >
CAMG P1,HIHIGH ;SKIP IF LAST RECORD WAS HIGHEST
SKIPA T1,HIHIGH ;ELSE LOAD AND SKIP IF NOT
SOS T1,P1 ;CONVERT TO LAST LOADED FROM FIRST FREE
PUSHJ P,OCTOUT ;MENTION HIGHEST ADDRESS
MOVSI T3,-BOTBLK ;# OF BLOCKS IN BOOT BUFFER
;SCAN THE INCORE BUFFER AND FIND NON-ZERO BLOCKS TO WRITE TO DISK
LDBNLP: MOVEI T1,(T3) ;COPY BLOCK #
IMULI T1,^O200 ;CONVERT TO OFFSET ADDRESS
MOVEI T2,(T1) ;COPY CURRENT memory ADDRESS
HRLI T2,-200 ;CONSTRUCT AOBJN
SKIPN BOTBUF(T2) ;ANYTHING IN THIS WORD
AOBJN T2,.-1 ;OR IN THIS BLOCK?
JUMPGE T2,SKPBLK ;NO, SKIP THIS BLOCK
MOVEI T1,(T3) ;GET BLOCK NUMBER
PUSHJ P,SUSET ;POSITION TO IT
MOVEI T1,(T3) ;COPY DISK BLOCK #
IMULI T1,^O200 ;COMPUTE OFFSET
ADDI T1,BOTBUF-1 ;CONVERT TO ABSOLUTE DF10 ADDRESS
HRLI T1,-200 ;# OF WORDS TO WRITE TO DISK
SETZ T2, ;END THE IO LIST
OUTPUT VIO,T1 ;OUTPUT THE BLOCK
SKPBLK: AOBJN T3,LDBNLP ;ADVANCE AND LOOP
PJRST CRLF
; G10WRD - GET A PDP11 WORD (2 BYTES)
G10WRD: PUSHJ P,G10BYT ;GET A BYTE
PUSH P,T1 ;SAVE IT
PUSHJ P,G10BYT ;GET ANOTHER BYTE
LSH T1,^D8 ;MAKE ROOM FOR 1ST BYTE GOTTEN
POP P,T2 ;GET BACK 1ST BYTE
OR T1,T2 ;COMBINE
POPJ P,0 ;RETURN THE WORD
; G10BYT - GET A PDP11 BYTE
G10BYT: SKIPE PFLAG ;SKIP IF NOT PACKED 4 PER PDP10 WORD
JRST GETPAK ; BRANCH TO GET DATA FROM PACKED WORDS
SOSGE BOTCNT ;SKIP IF THERE ARE BYTES LEFT IN BUFFER
JRST GETBUF ; BRANCH IF THE BUFFER IS EMPTY
AOS T1,BOTPTR ;GET POINTER TO BYTE
MOVE T1,(T1) ;GET BYTE FROM BUFFER
MOVE T2,CHKVAL ;GET CURRENT CHECKSUM
ADD T2,T1 ;COMPUTE NEW CHECKSUM
ANDI T2,377 ;KEEP ONLY LOW BYTE OF CHECKSUM DATA
MOVEM T2,CHKVAL ;RESTORE CHECKSUM
POPJ P,0
;HERE TO EXTRACT THE NEXT BYTE IF BUFFER IS IN PACKED MODE
GETPAK: MOVE T1,BYTNUM ;GET NUMBER OF THIS BYTE
IDIVI T1,4 ;COMPUTE WORD/BYTE IT FALLS IN
CAIN T1,^D128
JRST GETBUF ;GET NEXT BOTDAT
MOVE T1,BOTDAT(T1) ;GET THE WORD
LDB T1,[POINT ^D8,T1,17
POINT ^D8,T1,9
POINT ^D8,T1,35
POINT ^D8,T1,27](T2)
AOS T2,BYTNUM ;GET NEXT BYTE NEXT TIME
POPJ P,0
;HERE TO READ ANOTHER PDP10 DISK BLOCK FROM .BIN FILE
GETBUF: INPUT FIO,[IOWD 200,BOTDAT
0]
SETZM BYTNUM ;START WITH BYTE 0
MOVEI T1,^D128;INITIALIZE COUNT TO 128 (IE: 1 BYTE / 1 PDP10 WORD)
MOVEM T1,BOTCNT ;INITIALIZE THE COUNTER
MOVEI T1,BOTDAT-1 ;POINT AT DATA
MOVEM T1,BOTPTR ;INITIALIZE THE POINTER
;LOOP THRU DATA AND SET "PFLAG" IF THE HIGH BITS ARE USED IN THE
;PDP10 WORD (WHICH WOULD IMPLY DATA IS PACKED 4 PDP11 BYTES PER 1 PDP10 WORD)
MOVE T1,[-200,,BOTDAT]
MOVE T2,[-1,,777400]
TDNE T2,(T1)
SETOM PFLAG ;PACKED AFTER ALL
AOBJN T1,.-2 ;LOOK THRU ENTIRE BOTDAT IN CASE PATHOGENIC DATA
JRST G10BYT
;ROUTINE TO MENTION THE RANGE OF THE LAST LOADED RECORD FROM THE .BIN FILE
TELHGH: SKIPN LASTHI
POPJ P,
TYPE < THRU >
MOVE T1,LASTHI
PUSHJ P,OCTOUT
PJRST CRLF
SUBTTL COMMANDS -- EXIT
C$EXIT: MONRT. ;EXIT TO MONITOR
POPJ P, ;IF CONTINUE TYPED
SUBTTL COMMANDS -- PATH
C$PATH: PUSHJ P,TTYPHY ;SETUP TTY:
PUSHJ P,FILIN ;READ IN A SPEC
SKIPN FP,IPLIST ;MUST BE 1 SPEC
PUSHJ P,ILLCMD ;ELSE SYNTAX ERROR
SKIPE .FXLNK(FP) ;MUST BE *ONLY* ONE
PUSHJ P,ILLCMD
MOVSI T1,(FP) ;ORIGIN FDB
HRRI T1,DEFFDB ;DEFAULT FDB
BLT T1,DEFFDB+.FXLEN-1 ;COPY TO DEFAULT FDB
POPJ P,
SUBTTL COMMANDS -- HELP
.HELPR::ERROR <.HELPR is not loaded>
C$HELP: PUSHJ P,TTYPHY ;SETUP TTY:
TYPE <
F11 is a simple minded program to maintain a front end disk pack
>
MOVEI T1,CMDTXT
C$HEL0: SKIPN CMDSIX-CMDTXT(T1) ;SKIP ANY MORE COMMANDS
JRST C$HEL1
MOVE P1,(T1)
HRLI P1,(POINT 7,0)
PUSHJ P,TYPE.1
AOJA T1,C$HEL0
C$HEL1: PUSHJ P,TYPE..
CAI ENDING
PJRST CRLF
ENDING: ASCIZ @
The str:/vol: must be MOUNTed to TOPS10 for all commands, except INI/FULL.
The disk: must be DIS-MOUNTed to TOPS10 for INI/FULL.
INI/FULL will COMPLETELY DESTROY the TOPS10 file structure on disk:.
All switches in all commands are optional - a (hopefully) reasonable
action is taken in their absence.
All missing parts of all file specifications are always wild, except vol:.
vol: must always be specified and can never be wild.
F11 should not be used at all if the vol/str/disk is "MOU"nted to RSX20F.
@
SUBTTL COMMANDS -- INDEX
C$INDE: PUSHJ P,FILIN ;GET A FILE SPECIFICATION
SETZM TOTFIL ;INIT FILE TOTALS
SETZM TOTBLK
SKIPN FP,IPLIST ;LOAD POINTER TO LIST OF FILES
MOVEI FP,DEFFDB
PUSHJ P,SETTTY ;SETUP TERMINAL OUTPUT FILE
C$IND0: PUSHJ P,C$IND1 ;CALL INDEX SUBROUTINE
HRRZ FP,.FXLNK(FP) ;STEP TO NEXT SPEC, IF ANY
JUMPN FP,C$IND0 ;LOOP IF ANOTHER
PJRST TYPTOT ;TELL TOTALS AND EXIT
; SUBROUTINE TO DO AN "INDEX" OF THE "CURRENT" FILE SPEC (IE: @FP)
C$IND1: PUSHJ P,SAVFF ;SAVE CORE FOR COLLAPSE LATTER
PUSHJ P,OPNVOL ;GO OPEN THE VOLUME
MOVEI P1,1 ;START WITH FILE #1
C$IND2: MOVEI T1,-1(P1) ;GET IBM NUMBER
IDIVI T1,^D32 ;
ADD T1,IBMINC ;COMPUTE WORD ADDRESS FOR THAT FHB
MOVE T2,B32TBL(T2) ;FIND MASK FOR THAT FHB
TDNN T2,@T1 ;SKIP IF THAT FHB IN USE
JRST C$IND3 ;BRANCH IF FHB NOT IN USE
AOS TOTFIL ;COUNT A FILE
MOVEI T1,(P1) ;COPY FILE #
MOVEI T2,FHBBUF ;READ INTO NORMAL BUFFER
PUSHJ P,REDFHB ;READ THE FHB FOR THAT FILE
MOVEI T1,FHBBUF
PUSHJ P,TYPFHB ;TYPE INFO ON THAT FHB
C$IND3: ADDI P1,1 ;STEP TO NEXT FILE #
LOAD. T1,FMAX ;GET MAX # FILES
CAMG P1,T1 ;SKIP IF END OF FILES
JRST C$IND2 ;GO DO NEXT ONE TOO
POPJ P, ;RETURN TO CALLER,INDIRECTLY THRU SAVFF
SUBTTL COMMANDS -- DELETE
C$DELE: PUSHJ P,TTYPHY ;FORCE OUTPUT TO PHYSICAL TTY ONLY
PUSHJ P,FILIN ;GO GET FILE LIST
SKIPN FP,IPLIST ;MUST BE AT LEAST 1 FILE
PUSHJ P,ILLCMD ;GO COMPLAIN IF NO FILES SEEN
C$DEL0: MOVE T1,[FX.EQL] ;MUST NOT BE ANY =S
TDNE T1,.FXMOD(FP) ;SKIP IF NO =S SEEN
PUSHJ P,ILLCMD ;COMPLAIN IF =S SEEN
HRRZ FP,.FXLNK(FP) ;STEP TO NEXT FILE IF ANY
JUMPN FP,C$DEL0 ;AND LOOP TO CHECK FOR = IN ALL FILES
MOVE FP,IPLIST ;POINT AT 1ST FILE AGAIN
PUSHJ P,C$DEL1 ;GO DELETE A FILE
HRRZ FP,.FXLNK(FP) ;STEP TO NXT FILE, IF ANY
JUMPN FP,.-2 ;LOOP FOR ALL FIELS
POPJ P,0
; HERE TO DELETE ALL FILES IN A SINGLE SPEC
C$DEL1: PUSHJ P,SAVFF ;SAVE CORE
TDZ F,[X%INTRO] ;INDICATE HERALD NOT YET TYPED
PUSHJ P,OPNVOL ;OPEN THE FILES-11 VOLUME
PUSH P,VOLTAL ;SAVE VOLUME FREE TALLY FOR LATER
PUSHJ P,RLDINI ;INITIALIZE THE WILD CARD READER
MOVE T1,.FXSWT(FP) ;GET SWITCHES
TDNE T1,[S$FILE] ;/FILENUMBER?
JRST C$DEL5 ;YES, GO DO SPECIAL WORK
C$DEL2: MOVEI T1,(FP) ;POINT AT THIS BLOCK
MOVEI T2,DELFDB ;POINT AT THE DELETE FDB
PUSHJ P,NXTFDB ;FIND A FILE TO DELETE
JRST C$DEL4 ;GO UPDATE THE IBM/SBM
MOVE T1,.FXNUM+DELFDB ;GET FILE NUMBER
MOVEI T2,FHBBUF ;GET BUFFER FOR FHB
PUSHJ P,REDFHB ;GO READ THE FHB FOR THAT FILE
PUSHJ P,DELCHK ;SKIP IF PERMISSIBLE TO DELETE
TYPE <% Cannot delete file >,C$DEL3
MOVEI T1,FHBBUF ;POINT AT INCORE FHB
PUSHJ P,DELFHB ;GO DLEETE IT
TDON F,[X%INTRO] ;SKIP IF HERALD ALREADY TYPED
TYPE <Files deleted:
>
C$DEL3: MOVEI T1,FHBBUF ;POINT AT INCORE FHB
PUSHJ P,TYPFHU ;TYPE INFO ON THAT FHB
PUSHJ P,CRLF ;TYPE CRLF
JRST C$DEL2 ;LOOP FOR ANOTHER MATCH
;HERE AFTER DELETING ALL FILES MATCHES A SINGLE FILE SPEC
C$DEL4: PUSHJ P,WRTSBM ;UPDATE THE SBM
PUSHJ P,WRTIBM ;UPDATE THE IBM
POP P,T1 ;GET BACK THE ORIGINAL FREE TALLY
MOVNS T1 ;-VE FREE TALLY
ADD T1,VOLTAL ;COMPUTE # OF BLOCKS FREED
JUMPE T1,CPOPJ ;DON'T MENTION IT IF NONE HAPPENED
PUSHJ P,DECOUT
TYPE < blocks freed>
PJRST CRLF ;ALL DONE
;HERE IF USER GAVE DELETE/FILE:n
C$DEL5: MOVE T1,V$FILE(FP) ;GET FILE NUMBER OF FILE TO DELETE
SUBI T1,1 ;GET BIT NUMBER FOR THE FILE
IDIVI T1,^D32 ;COMPUTE WORD IN MAP
ADD T1,IBMINC ;COMPUTE ADDRESS OF CORRECT BIT
MOVE T2,B32TBL(T2) ;GET CORRECT BIT
ANDCAM T2,@T1 ;TURN OFF BIT IN INDEX MAP
JRST C$DEL4 ;REJOIN COMMON CODE
;ROUTINE TO CHECK IF DELETING A FILE MIGHT CAUSE A CORRUPT STRUCTURE
;DON'T ALLOW DELETE OF THE "KNOWN" FILES INDEXF,BITMAP,BADBLK,CORIMG,000000
;DON'T ALLOW DELETE OF "PROTECTED" FILES *.NDL;*[*]
;DON'T ALLOW DELETE OF .DIR FILES THAT CONTAIN ACTIVE ENTRIES
DELCHK: MOVE T1,.FXSWT(FP) ;GET SWITCHES
TDNE T1,[S$NOCHECK] ;SKIP IF NOT /NOCHECK
JRST CPOPJ1 ;ALLOW IT IF /NOCHECK
MOVE T1,.FXNUM+DELFDB ;GET FILE'S NUMBER
HLRZ T2,.FXEXT+DELFDB ;GET FILE'S TYPE
CAILE T1,4 ;SKIP IF A KNOWN FILE
CAIN T2,'NDL' ;SKIP IF NOT PROTECTED FILE
POPJ P, ;BAD RETURN IF KNOWN FILE OR DIRECTORY
CAIE T2,'DIR' ;SKIP IF A DIRECTORY FILE
JRST CPOPJ1 ;GIVE SKIP (GOOD) RETURN
PUSHJ P,SAVE1 ;SAVE SOME ACS
MOVSI P1,-^D100 ;I HOPE NO DIR FILE IS EVEN THIS BIG!
DELCH1: MOVEI T1,FHBBUF ;POINT AT THE INCORE FHB
MOVEI T2,(P1) ;GET RBN OF DIR FILE
PUSHJ P,SCNRET ;FIND THIS RBN
JRST CPOPJ1 ;IF WE RUN OUT OF BLOCKS, THEY'RE ALL 0S
PUSHJ P,SUSET ;POSITION TO IT
IN VIO,[IOWD 200,TMPBUF ;READ IN THE DIRECTORY DATA BLOCK
0] ;
SKIPA T1,[-200,,0] ;SET UP AOBJN POINTER IF I/O IS GOOD
TYPE <% I/O error scanning directory entries>,CRLF
SKIPN TMPBUF(T1) ;SKIP IF WE FOUND SOME DATA
AOBJN T1,.-1 ;LOOP UNTIL WE SCAN ENTIRE BLOCK
JUMPL T1,CPOPJ ;EXIT IF WE FIND DATA IN BLOCK
AOBJN P1,DELCH1 ;ADVANCE TO NEXT BLOCK
POPJ P, ;IF WE RUN OUT OF BLOCKS, WE LOSE
;ROUTINE TO ZERO THE OWNING DIRECTORY'S POINTERS TO A FILE
;WHICH HAS BE LOCATED VIA THE "WILD 20F" MECHANISM
DELFHB: PUSHJ P,RETFHB ;RETURN FHB TO FREE POOL
MOVE P1,WDIOFF ;GET POINTER USED BY WILD SCANNER
SUBI P1,.DIROFF ;BACK OFF TO PREVIOUS (MATCHING) RECORD
STOR. [0],UFN1,P1 ;STORE 0S
STOR. [0],UFN2,P1 ;...INTO ALL
STOR. [0],UFN3,P1 ;...OF THE
STOR. [0],UFTY,P1 ;...DIRECTORY
STOR. [0],UFNO,P1 ;...ENTRY
STOR. [0],UFSQ,P1 ;...
STOR. [0],UFRV,P1 ;...
STOR. [0],UVER,P1 ;...
PUSHJ P,UPDDIR ;GO UPDATE THE DIRECTORY
TYPE <% OUT UUO failed to update directory and remove file reference
>
POPJ P,0
;ROUTINE TO RE-WRITE THE LAST DIRECTORY BLOCK SCANNED BY THE WILD SCANNER
;USED TO HANDLE INSERTS, DELETES, RENAMES, ETC
UPDDIR: MOVE T1,WDIPBN ;GET BLOCK WHERE FILE NAME IS
PUSHJ P,SUSET ;POSITION DISK
OUT VIO,[IOWD 200,WDIBUF ;...WRITE OUT DIRECTORY BLOCK WITHOUT FILE
0] ;
JRST CPOPJ1
POPJ P, ;RETURN
SUBTTL COMMANDS -- DIRECT
C$DIRE: PUSHJ P,FILIN ;GET A FILE SPECIFICATION
SETZM TOTFIL
SETZM TOTBLK
SKIPN FP,IPLIST ;SKIP IF THERE WAS A FILE
MOVEI FP,DEFFDB ;USE DEFAULT VOL SPEC IF OMITTED
PUSHJ P,C$DIR0 ;CALL SUBROUTINE TO DO "DIR" COMMAND
HRRZ FP,.FXLNK(FP) ;POINT TO NEXT FILE SPEC, IF ANY
JUMPN FP,.-2 ;LOOP IF ANOTHER
TYPTOT: TYPE <Grand total of > ;
MOVE T1,TOTBLK
PUSHJ P,DECOUT
TYPE < blocks in >
MOVE T1,TOTFIL
PUSHJ P,DECOUT
TYPE < files>
JRST CRLF ;RETURN
;SUBROUTINE TO DO A "DIRECT" COMMAND ON THE CURRENT INPUT SPEC
C$DIR0: PUSHJ P,SAVFF ;SAVE CORE LIMITS FOR COLLAPSE LATTER
PUSHJ P,SAVE1 ;SAVE AN AC
PUSHJ P,SETTTY ;SETUP TTY OUTPUT FILE IF ANY
PUSHJ P,OPNVOL ;OPEN THE VOLUME FOR I/O
PUSHJ P,RLDINI ;INITIALIZE RSX20F WILD CARD FILE
SETO P1, ;"REMEMBER" OLD UFD NAME
C$DIR1: MOVEI T1,(FP) ;POINT AT INPUT FDB
MOVEI T2,INPFDB ;PUT RSX20F FILE IN INPFDB
PUSHJ P,NXTFDB ;GET A FILE BLOCK
JRST [RELEAS TTY,
POPJ P,0] ;RETURN WHEN NO MORE MATCHES
AOS TOTFIL
PUSHJ P,UFDCHK ;CHECK FOR DIRECTORY CHANGE
MOVE T1,.FXNUM+INPFDB ;GET ABSOLUTE FILE #
MOVEI T2,FHBBUF ;READ INTO NORMAL BUFFER
PUSHJ P,REDFHB ;READ FHB
PUSHJ P,CHKFNM ;CHECK IF FILE NAME IN DIRECTORY AND
; FHB MATCH, PRINT MESSAGE IF NOT
MOVEI T1,FHBBUF ;POINT AT THIS FILE'S FHB
PUSHJ P,TYPFHB ;TYPE FHB
JRST C$DIR1 ;GO TO NEXT FILE
;ROUTINE TO GIVE A CRLF BETWEEN DIRECTORYS
UFDCHK: CAMN P1,DIRCNT ;SKIP IF DIRECTORY CHANGED
POPJ P, ;EXIT IF DIRECTORY STAYED THE SAME
MOVE P1,DIRCNT ;REMEMBER THE DIRECTORY
PUSHJ P,CRLF ;GIVE A BLANK LINE
MOVE T1,FEUNIT ;GET NAME OF CURRENT FILE'S VOLUME
PUSHJ P,SIXOUT ;TYPE CURRENT FILE'S VOLUME
TYPE <:> ;TYPE SEPERATOR
DMOVE T1,UFDNAM ;GET DIRECTORY NAME
PUSHJ P,TYPDIN ;TYPE DIRECTORY NAME
PJRST CRLF
;ROUTINE TO CHECK IF FILE NAME IN DIRECTORY ENTRY AND FHB MATCH.
;IF NOT, A MESSAGE IS PRINTED. WDIOFF CONTAINS DIRECTORY, FHBBUF
;CONTAINS FHB.
CHKFNM: PUSHJ P,SAVE2 ;FREE UP AN AC OR TWO
MOVE P1,WDIOFF ;GET DIRECTORY ENTRY ADDRESS
SUBI P1,.DIROFF ;(WAS POST-INCREMENTED)
MOVEI P2,FHBBUF-FHBBUF ;OFFSET FOR FHB
LOAD. T1,UFN1,P1 ;GET FIRST PART OF NAME
LOAD. T2,FNM1,P2 ;DITTO FROM FHB
CAME T1,T2 ;MATCH?
JRST CHKFNE ;NO
LOAD. T1,UFN2,P1 ;GET SECOND PART OF NAME
LOAD. T2,FNM2,P2 ;DITTO FROM FHB
CAME T1,T2 ;MATCH?
JRST CHKFNE ;NO
LOAD. T1,UFN3,P1 ;GET THIRD PART OF NAME
LOAD. T2,FNM3,P2 ;DITTO FROM FHB
CAME T1,T2 ;MATCH?
JRST CHKFNE ;NO
LOAD. T1,UFTY,P1 ;GET TYPE
LOAD. T2,FTYP,P2 ;DITTO FROM FHB
CAME T1,T2 ;MATCH?
JRST CHKFNE ;NO
LOAD. T1,UVER,P1 ;GET VERSION
LOAD. T2,FVER,P2 ;DITTO FROM FHB
CAMN T1,T2 ;MATCH?
POPJ P, ;FHB AND DIRECTORY MATCH
CHKFNE: TYPE <% Name in header block of >
LOAD. T1,UFN1,P1 ;GET 1ST WORD OF FILE NAME
LOAD. T2,UFN2,P1 ;GET 2ND WROD OF FILE NAME
LOAD. T3,UFN3,P1 ;GET 3RD WORD OF FILE NAME
PUSHJ P,FILE5O ;TYPE OUT FILE NAME
TYPE <.>
LOAD. T1,UFTY,P1
SETZB T2,T3 ;DON'T WANT EXTRA SPACING
PUSHJ P,FILE5O
TYPE <;>
LOAD. T1,UVER,P1 ;GET VERSION #
PUSHJ P,OCTOUT ;TYPE IT
TYPE < is >
LOAD. T1,FNM1,P2 ;GET 1ST WORD OF FILE NAME
LOAD. T2,FNM2,P2 ;GET 2ND WROD OF FILE NAME
LOAD. T3,FNM3,P2 ;GET 3RD WORD OF FILE NAME
PUSHJ P,FILE5O ;TYPE OUT FILE NAME
TYPE <.>
LOAD. T1,FTYP,P2
SETZB T2,T3 ;DON'T WANT EXTRA SPACING
PUSHJ P,FILE5O
TYPE <;>
LOAD. T1,FVER,P2 ;GET VERSION #
PUSHJ P,OCTOUT ;TYPE IT
PJRST CRLF ;END WITH NEW LINE
SUBTTL COMMANDS -- VOLUME
C$VOLU: PUSHJ P,FILIN ;GET A FILE SPECIFICATION
SKIPN FP,IPLIST ;LOAD INPUT FILE LIST POINTER
MOVEI FP,DEFFDB
PUSHJ P,SETTTY ;SETUP TERMINAL OUTPUT FILE
PUSHJ P,C$VOL0 ;DO THE "VOLUME" COMMAND TO ONE SPEC
HRRZ FP,.FXLNK(FP) ;STEP TO NEXT FIEL SPEC, IF ANY
JUMPN FP,.-2 ;LOOP IF ANOTHER FILE SPEC
POPJ P,0
;TYPE RANDOM INFORMATION EXTRACTED FROM A VOLUME'S FILES-11 HOME BLOCK
C$VOL0: PUSHJ P,SAVFF ;SAVE .JBFF
PUSHJ P,OPNVOL ;GO OPEN THE VOLUME
TYPE <Volume creation: >
MOVE T1,[XWD O.VDAY,A.VDAY] ;GET PDP11 BYTE POINTER
SETZ P1, ;NO OFFSET
PUSHJ P,TYPDAT ;TYPE DATE
TYPE < >
MOVE T1,[XWD O.VHOR,A.VHOR] ;GET BYTE POINTER
SETZ P1, ;NO OFFSET
PUSHJ P,TYPTIM ;TYPE CREATION TIME
PUSHJ P,CRLF
TYPE <FILES-11 home block at block >
MOVE T1,H11LBN ;GET BLOCK NUMBER OF HOME BLOCK
PUSHJ P,OCTOUT ;TYPE BLOCK NUMBER OF HOME BLOCK
PUSHJ P,CRLF
TYPE <Volume spans blocks >
MOVE T1,FSTLBN ;GET FIRST BLOCK # ALLOCATED TO VOLUME
PUSHJ P,OCTOUT ;TYPE FIRST BLOCK # ALLOCATED TO VOLUME
TYPE < through block >
MOVE T1,LSTLBN ;GET LAST BLOCK # ALOCATED TO VOLUME
PUSHJ P,OCTOUT ;TYPE LAST BLOCK # ALLOCATED TO VOLUME
PUSHJ P,CRLF
MOVE T1,LSTLBN ;GET LAST LBN IN VOLUME
SUB T1,FSTLBN ;GET FIRST LBN IN VOLUME
ADDI T1,1 ;1 MORE
PUSHJ P,DECOUT ;TYPE COMPUTED # BLOCKS IN VOLUME
TYPE < blocks allocated to FILES-11 volume, >
MOVE T1,VOLTAL ;GET # BLOCKS SEEN AS FREE
PUSHJ P,DECOUT ;TYPE # BLOCKS SEEN AS FREE
TYPE < blocks free>
PUSHJ P,CRLF
TYPE <Index-bit-map at block >
MOVE T1,IBMLBN ;GET INDEX-BIT-MAP LOCATION
PUSHJ P,OCTOUT ;TYPE LOCATION OF INDEX-BIT-MAP
TYPE <, >
LOAD. T1,IBSZ ;GET SIZE OF INDEX-BIT-MAP
PUSHJ P,DECOUT ;TYPE SIZE OF INDEX-BIT-MAP
TYPE < blocks long>
PUSHJ P,CRLF
LOAD. T1,FMAX ;GET MAX # OF FILES PERMITTED
PUSHJ P,DECOUT ;TYPE MAX# OF FILES PERMITTED
TYPE < files possible, >
MOVE T1,FHBTAL ;GET TALLY OF FREE FHBS
PUSHJ P,DECOUT ;TYPE TALLY OF FREE FHBS
TYPE < files remain unallocated>
; MORE OF THE VOLUME INFO CODE
PUSHJ P,CRLF
TYPE <Storage-bit-map cluster size >
LOAD. T1,SBCL ;GET VOLUME'S SBM CLUSTER SIZE
PUSHJ P,DECOUT ;TYPE CLUSTER SIZE
PUSHJ P,CRLF ;START A NEW LINE
TYPE <Device type: >
LOAD. T1,DVTY ;GET DISK DEVICE TYPE
PUSHJ P,OCTOUT ;TYPE IT
PUSHJ P,CRLF ;START A NEW LINE
TYPE <Structure level: > ;
LOAD. T1,VLEV ;GET STRUCTURE LEVEL
PUSHJ P,OCTOUT ;TYPE IT
PUSHJ P,CRLF
TYPE <Volume name: ">
MOVE T1,[XWD O.VNAM,A.VNAM] ;GET PDP11 BYTE POINTER
PUSHJ P,TYPS12 ;TYPE 12 BYTES (IE: VOLUME NAME)
TYPE <">
PUSHJ P,CRLF
TYPE <Volume owner's uic: >
LOAD. T1,VOWN ;GET UIC
LSH T1,-^D8 ;CHOP OFF RIGHT HALF
PUSHJ P,OCTOUT ;TYPE FIRST PART OF UIC
TYPE <,>
LOAD. T1,VOWN ;GET UIC
ANDI T1,377 ;CHOP OFF LEFT HALF
PUSHJ P,OCTOUT ;TYPE 2ND PART OF UIC
PUSHJ P,CRLF
TYPE <Volume protection: >
LOAD. T1,VPRO ;GET VOLUME PROTECION
PUSHJ P,P11OUT ;TYPE VOLUME PROTECTION
PUSHJ P,CRLF
TYPE <Volume characteristics: >
LOAD. T1,VCHA ;GET VOLUME CHARACTERISTICS BYTE
PUSHJ P,OCTOUT ;TYPE OCTAL VALUE OF CHARACTERITSTICS
PUSHJ P,CRLF
TYPE <Default file protection: >
LOAD. T1,DFPR ;GET DEFAULT FILE PROTECTION
PUSHJ P,P11OUT ;TYPE FILE PROTECTION
PUSHJ P,CRLF
TYPE <# of retrieval pairs in a window: >
LOAD. T1,WISZ ;GET # OF PAIRS
PUSHJ P,DECOUT ;TYPE SIZE OF WINDOW
PUSHJ P,CRLF
TYPE <Default # of blocks in file extends: >
LOAD. T1,FIEX ;GET SIZE OF EXTENSION
PUSHJ P,DECOUT ;TYPE SIZE TO USE WHEN EXTENDING
; STILL MORE VOLUME INFO CODE
PUSHJ P,CRLF
TYPE <# Entries in a directory LRU: >
LOAD. T1,LRUC ;GET SIZE OF LRU
PUSHJ P,DECOUT ;TYPE SIZE OF LRU
PUSHJ P,CRLF
TYPE <System independent volume name: ">
MOVE T1,[O.INDN,,A.INDN] ;GET BYTE POINTER TO VOLUME NAME
PUSHJ P,TYPS12 ;TYPE 12 BYTE OF VOLUME NAME
TYPE <">
PUSHJ P,CRLF
TYPE <System independent owners name: ">
MOVE T1,[O.INDO,,A.INDO] ;GET BYTE POINTER TO OWNER'S NAME
PUSHJ P,TYPS12 ;TYPE OWNER'S NAME
TYPE <">
PUSHJ P,CRLF
TYPE <System independent format type: ">
MOVE T1,[O.INDF,,A.INDF] ;GET BYTE POINTER TO FORMAT TYPE
PUSHJ P,TYPS12 ;TYPE 12 BYTES OF FORMAT TYPE
TYPE <">
PUSHJ P,CRLF
MOVE T1,.FXSWT(FP) ;GET SWITCHES
TDNN T1,[S$DETAIL] ;SKIP IF /DETAIL REQUESTED
POPJ P, ;EXIT WITHOUT MAP DATA IF NOT /DETAIL
PJRST TYPSBM
; ROUTINE TO TYPE 12 PDP11 ASCII BYTES GIVEN PDP11 BYTE POINTER IN T1
TYPS12: PUSHJ P,SAVE1 ;SAVE AN AC
MOVEI P1,^D12 ;INIT THE COUNTER
TYPS13: PUSHJ P,TYPBYT ;GET&TYPE BYTE USING BYTE POINTER IN T1
SOJG P1,TYPS13 ;LOOP TILL ALL BYTES TYPED
POPJ P, ;RETURN TO CALLER
SUBTTL COMMANDS -- GET
C$GET: PUSHJ P,FILIN ;GET FILE SPEX
SKIPN FP,IPLIST ;GET FILE INPUT LIST
MOVEI FP,DEFFDB
C$GET1: PUSHJ P,SETOUT ;GRAB AN OP FDB IF ANY THERE
PUSHJ P,C$GETA ;GO DO PER VOLUME INIT
HRRZ FP,.FXLNK(FP) ;STEP TO NEXT INPUT SPEC
JUMPN FP,C$GET1 ;LOOOP IF MORE
POPJ P, ;RETURN TO CALLER
; HERE TO START A FILE COPY USING THE CURRENT INPUT FILE SPEC
C$GETA: PUSHJ P,SAVFF ;SAVE PER-VOLUME CORE SIZE
PUSHJ P,OPNVOL ;OPEN THE FILES-11 VOLUME
PUSHJ P,RLDINI ;YES, INITIALIZE THE WILD READER
C$GET2: MOVEI T1,(FP) ;POINT T1 AT USER'S FILE SPEC
MOVEI T2,TMPFDB ;POINT AT OUTPUT FDB
PUSHJ P,NXTFDB ;GET THE NEXT MATCHING FILE
POPJ P, ; NO MORE WILD FILES, EXIT THIS LEVEL
PUSHJ P,C$GETB ;GO DO COPY FOR THIS FILE
JRST C$GET2 ;AND LOOP FOR ANOTHER
; HERE TO COPY A SINGLE NON-WILD FILE FROM FILES11 TO TOPS10
C$GETB: PUSHJ P,SAVFF ;SAVE .JBFF SO WE CAN COLAPSE CORE LATER
SETOM RSXCTR ;INIT THE BYTE COUNTER
SETOM RSXVBN ;INIT THE BLOCK POINTER
MOVE T1,.FXNUM+TMPFDB ;GET THE FILE NUMBER OF THE MATCH
MOVEI T2,FHBBUF ;NORMAL HEADER BUFFER
PUSHJ P,REDFHB ;GO READ THAT FILE'S FFHB
PUSHJ P,G$ENTER ;GO DO THE ENTER FOR "GET" COMMAND
MOVE T1,.FXSWT+TMPFDB ;GET MODE FLAGS
TDNN T1,[S$ASCI] ;SKIP IF EXPLICIT /ASCII
TDNN T1,[S$IMAG!S$BINA] ;SKIP IFF EXPLICIT BINARY
JRST C$GET5 ;BRANCH IF ASCII COPY
;FALL THROUGH TO DO IMAGE MODE COPY
;HERE TO XFER A FILE FROM FE DISK TO 10 DISK IN BINARY MODE
C$GET3: MOVEI T1,FHBBUF ;POINT AT FHB BUFFER FOR THAT FILE
AOS T2,RSXVBN ;LOAD T2=NEXT VBN
PUSHJ P,SCNRET ;SCAN "RIB" AND FIND NEXT BLOCK #
JRST C$GET4 ;FAILED, MUST BE EOF
PUSHJ P,SUSET ;POSITION TO IT
IN VIO,[IOWD 200,TMPBUF ;READ THAT BLOCK INTO BUFFER
0] ;...
SKIPA T2,RSXVBN ;GET VBN AGAIN
PUSHJ P,G$IER ;GO REPORT INPUT ERROR, THEN RETURN HERE
MOVEI T1,FHBBUF ;POINT AT FHB FOR INPUT FILE
PUSHJ P,EOFBYT ;GET # OF PDP11 BYTES IN BLOCK
IDIVI T1,4 ;COMPUTE T1=# PDP10 WORDS
CAIE T2,0 ;ANY LEFT OVER BYTES?
ADDI T1,1 ;IF SO, USE ONE MORE PDP10 WORD
IMUL T1,[-1,,0] ;CONVERT INTO -VE.COUNT,,0
SKIPE T1 ;SHOULD NOT HAPPEN, BUT AVOID GOTO WORDS
HRRI T1,TMPBUF-1 ;INSERT BUFFER ADDRESS INTO IOWD WORD
SETZ T2, ;END IOLIST WITH A 0 IOWD
OUT FIO,T1 ;WRITE THAT BLOCK INTO FILE
SKIPA ;SKIP IF OUTPUT GOOD
PUSHJ P,G$OER ;REPORT ERROR, THEN RETURN HERE
JRST C$GET3 ;LOOP TO XFER NEXT BLOCK IN FILE
;ROUTINE TO TYPE OUT DETAILS OF AN INPUT ERROR DURING "GET" COMMAND
G$IER: TYPE <% Input error > ;HERALD THE ERROR
GETSTS VIO,T1 ;GET I/O STATUS OF THAT CHANNEL
PUSHJ P,OCTOUT ;TYPE OUT I/O STATUS IN OCTAL
TYPE < on PBN > ;...
MOVE T1,LASSET ;GET PHYSICAL BLOCK# LAST SUSET'D TO
PUSHJ P,OCTOUT ;TYPE LAST BLOCK# SUSET'D TO
TYPE < (RBN > ;...
MOVE T1,RSXVBN ;GET RELATIVE BLOCK # IN FILE
PUSHJ P,OCTOUT ;TYPE RELATIVE BLOCK # IN FILE
TYPE <) of > ;...
MOVEI T1,FHBBUF ;POINT AT FHB FOR INPUT FILE
PUSHJ P,TYPFHU ;TYPE COMPLETE FILE11 FILE SPEC
SETSTS VIO,17 ;TURN OFF THE ERROR BITS
PJRST CRLF ;END WITH CRLF
;ROUTINE TO TYPE OUT DETAILS OF AN OUTPUT ERROR DURING "GET" COMMAND
G$OER: TYPE <% Output error > ;HERALD THE ERROR
GETSTS FIO,T1 ;GET THE I/O STATUS OF THAT CHANNEL
PUSH P,T1 ;SAVE BITS
PUSHJ P,OCTOUT ;TYPE I/O STATUS IN OCTAL
TYPE < on RBN > ;...
MOVE T1,RSXVBN ;GET RELATIVE BLOCK# IN OUTPUT FILE
PUSHJ P,OCTOUT ;TYPE BLOCK # IN OCTAL
TYPE < of > ;...
PUSHJ P,TYPFIO ;TYPE FILE SPEC FOR OUTPUT FILE
POP P,T1 ;GET BACK I/O STATUS BITS
TRZ T1,IO.ERR ;TURN OFF ERRORS
SETSTS FIO,(T1) ;TURN OFF ERROR BITS IN DDB
PJRST CRLF ;END WITH CRLF
; HERE WHEN WE GET EOF ON THE FILES-11 VOLUME'S FILE
C$GET4: MOVEI T1,FIO ;LOAD T1=CHANNEL # OF OUTPUT FILE
DEVCHR T1, ;GET DEVICE CHARACTERISTICS
TDNE T1,[DV.TTY] ;SKIP IF NOT USER'S TTY
OUTPUT FIO, ;GIVE HIM HIS OUTPUT IMMEDIATELY
PUSH P,FP ;SAVE FP
MOVEI FP,TMPFDB ;POINT AT OUTPUT FDB
PUSHJ P,TYPFIO ;TYPE ACTUAL OUTPUT SPEC
POP P,FP ;RESTORE FP
TYPE <=>
MOVEI T1,FHBBUF ;POINT AT INPUT FILE'S FHB
PUSHJ P,TYPFHU ;TYPE ACTUAL INPUT SPEC
MOVE T1,.FXSWT+TMPFDB ;GET MODE FLAGS
TDNN T1,[S$ASCI] ;SKIP IF EXPLICIT ASCII
TDNN T1,[S$IMAG!S$BINA] ;SKIP IF EXPLICIT BINARY
SKIPA T1,[SIXBIT ./ASCII.] ;HERE IF EXPLICIT OR IMPLICIT ASCII
MOVE T1,[SIXBIT ./IMAGE.] ;HERE IF EXPLICIT (ONLY) BINARY
PUSHJ P,SIXOUT ;TYPE MODE OF FILE XFER
TDZE F,[X%PEOF] ;DID WE HAVE A PROBLEM COPYING?
TYPE <(Unexpected end-of-file)>
PUSHJ P,CRLF ;END LINE
RELEASE FIO, ;RELEASE IT
SETZB T3,TTYOBF+.BFCTR ; ZERO TTY'S BYTE COUNT
PJRST TYO ;TYPE A NULL TO FORCE LINE OUT NOW
;HERE TO COPY AN ASCII TEXT FILE FROM THE FE DISK
C$GET5: LOAD. P4,RTYP ;GET RECORD TYPE BYTE FROM FHB
LOAD. P3,RATT ;GET RECORD ATTRIBUTE BYTE FROM FHB
C$GET6: LOAD. P2,RSIZ ;GET RECORD SIZE FROM FHB
TDZ F,[X%ODD] ;INITIALIZE ODD/EVEN RECORD SIZE FLAG
MOVE T3,P2 ;COPY RECORD SIZE
CAIN P4,R.FIX ;SKIP IF VARIABLE LENGTH RECORDS
JRST .+3 ;BRANCH IF FIXED RECORD SIZE
PUSHJ P,DVWORD ;GET RECORD SIZE FROM RECORD ITSELF
JRST C$GET4 ;BRANCH IF DVWORD FAILS (EOF, APPARENTLY)
MOVE P1,T3 ;COPY FINAL RECORD SIZE
CAIN P4,R.SEQ ;SKIP IFF NOT SEQUNCED RECORD
PUSHJ P,GETSEQ ;GET SEQUENCE NUMBER FROM RECORD HEADER
MOVE P2,P1 ;COPY BYTE COUNT AGAIN
CAIN P4,R.FIX ;SKIP IF VARIABLE LENGTH RECORD
JRST C$GET7 ;BRANCH IF FIXED LENGTH RECORD
TRNE P1,1 ;SKIP IF VARIABLE LENGTH RECORD WITH EVEN COUNT
TDO F,[X%ODD] ;REMEMBER IF VARIABLE LENGTH ODD COUNT
MOVEI T3,15 ;LOAD T3=CARRIAGE-RETURN
TRNE P3,FD.CR ;SKIP IF NO IMPLIED CR'S AT HEAD OF RECORD
PUSHJ P,PUTC ;INSERT IMPLIED CR AT HEAD OF RECORD
JUMPE P1,C$GET8 ;BRANCH IF BLANK LINE
;HERE TO COPY THE LINE
C$GET7: PUSHJ P,RDBYTE ;GET A BYTE FROM THE INPUT RECORD
JRST C$G7B ;BRANCH IF WE GET AN EOF DURING COPY OF RECORD
ANDI T3,177 ;TRUNCATE 8-BIT ASCII TO 7-BIT ASCII
CAIE T3,14 ;SKIP IF EMBEDDED <FORM-FEED> FOUND
CAIN T3,13 ;NONSKIP IF EMBEDDED <VERTICAL-TAB> FOUND
TDO F,[X%VMS] ;REMEMBER EXPLICIT VERTICAL MOTION SEEN
CAIE T3,12 ;SKIP IF EXPLICIT <LINE-FEED> FOUND
CAIN T3,15 ;NONSKIP IF EMBEDDED <CARRIAGE-RETURN> FOUND
JRST [TDO F,[X%VMS] ;REMEMBER VERTICAL MOTION SEEN
MOVE T4,[S$NOVM];GET THE "DON'T COPY CRLF" BIT
TDNE T4,.FXSWT(FP);SKIP IF ALLOWED TO COPY CR,LFS
JRST .+2 ;SKIP OVER "PUTC" SO CRLF IS NOT COPIED
JRST .+1] ;FALL THROUGH AND COPY CRLF
PUSHJ P,PUTC ;PUT INPUTED BYTE INTO OUTPUT FILE
SOJG P1,C$GET7 ;LOOP TO COPY MORE BYTES IF COUNT NOT EXPIRED
;HERE WHEN BYTE COUNT EXPIRES
C$GET8: MOVEI T3,12 ;LOAD T3=LINE FEED
TRNE P3,FD.CR ;SKIP IF NO IMPLIED CR AT END OF RECORD
PUSHJ P,PUTC ;INSERT IMPLIED CR AT END OF THIS RECORD
TDZN F,[X%VMS] ;SKIP IF VERTICAL MOTION CHARACTER WAS SEEN
TRNE P3,FD.CR ;SKIP IF NO IMPLIED CR/LFS
SKIPA ;NO NEED TO INSERT MOTION
PUSHJ P,FCRLF ;INSERT A CR, LF INTO THE OUTPUT TEXT FILE
TDZN F,[X%ODD] ;SKIP IF ODD BYTE STILL LEFT IN INPUT FILE
JRST C$GET6 ;BRANCH IF NO EXTRA ODD BYTE TO TAKE CARE OF
PUSHJ P,RDBYTE ;TRASH THE EXTRA ODD BYTE IF NECESSARY
JRST C$GET4 ;BRANCH TO EOF HANDLER IF RDBYTE FAILS
JRST C$GET6 ;LOOP FOR ANOTHER LINE
;ROUTINE TO GET FILES-11 SEQUENCE NUMBER FROM INPUT FILE
;...AND TYPE IT OUT TO TOPS-10 OUTPUT FILE
GETSEQ: PUSHJ P,DVWORD ;GET THE SEQ# FOR THIS RECORD
TYPE <% EOF while reading line sequence number>,C$GET4
SUBI P1,2 ;FIXUP BYTE COUNT WRT SEQUENCE # BYTES
PJRST TYPSQN ;RE-TYPE SEQUENCE # INTO OUTPUT FILE
;COME HERE DURING COPY OF A RECORD THAT RUNS OUT OF BYTES
C$G7B: CAME P1,FFBYTE ;SKIP IF EOF IN EXPECTED PLACE
TDO F,[X%PEOF] ;REMEMBER IF EOF WAS IN UNEXPECTED PLACE
JRST C$GET4 ;JOIN COMMON EOF HANDLER
; ROUTINE TO DO THE ENTER TO A TOPS10 FILE
; USED BY THE SINGLE FILE LOOP OF THE "GET" COMMAND
G$ENTE: PUSHJ P,GE$FIL ;SETUP ENTER'S FILE NAME DATA
PUSHJ P,GE$TYP ;SETUP ENTER'S FILE TYPE DATA
PUSHJ P,GE$SWT ;GO GET THE SWITCH INFO
MOVE T1,.FXDEV+OUTFDB ;GET OUTPUT DEVICE FROM WILD'S BLOCK
MOVEM T1,.FXDEV+TMPFDB ;INSERT DEVICE INTO SCAN'S BLOCK
MOVE T1,[OUTFDB+.FXDIR,,TMPFDB+.FXDIR] ;POINT AT WILD_PATH,,SCAN_PATH
BLT T1,TMPFDB+.FXDIR+.FXLND-1 ;XFER WILD'S PATH INTO SCAN'S BLOCK
MOVE T1,OUTFDB+.FXMOD ;GET WILD'S SWITCH BITS
MOVEM T1,TMPFDB+.FXMOD ;INSERT WILD'S BITS INTO SCAN'S BLOCK
MOVEI T1,TMPFDB ;POINT AT FILE SPEC BLOCK
MOVEI T2,OPNBLK ;POINT AT OPEN BLOCK
MOVEI T3,LERBLK ;POINT AT L/E/R BLOCK
MOVEI T4,PTHBLK ;POINT AT PATH BLOCK
PUSHJ P,.STOPB## ;CONSTRUCT OPEN/LER/PATH BLOCKS
ERROR <Cannot "setup" output file>
MOVEI T1,.RBSPL ;GET T1=LENGTH OF ENTER BLOCK
MOVEM T1,LERBLK+.RBCNT ;INSERT LENGTH INTO COUNT WORD
PUSHJ P,GE$CDT ;GO INSERT CREATE DATE/TIME
LOAD. T1,FVER ;GET ;GENERATION
MOVEM T1,LERBLK+.RBVER ;MAKE IT PDP10 VERSION "(nnn)-0"
MOVEI T1,.IOASC ;USE ASCII MODE FOR OUTPUT
MOVE T2,.FXSWT+TMPFDB ;GET MODE FLAGS
TDNE T2,[S$IMAG!S$BINA] ;/BINARY OR /IMAGE?
MOVEI T1,.IODMP ;THEN USE IMAGE MODE
MOVE T2,OPNBLK+1 ;GET SCAN'S CHOICE OF DEVICE
MOVSI T3,DOBUF ;
OPEN FIO,T1 ;OPEN IT
ERROR <Cannot OPEN output device>
ENTER FIO,LERBLK ;GO ENTER THE FILE
ERROR <Cannot ENTER output file>,LSTLER
SETZM PUTCTR ;INIT COUNTER
POPJ P,
;ROUTINE TO SETUP THE FILE NAME DATA PRIOR TO THE ENTER FOR A "GET" CMD
GE$FIL: LOAD. T1,FNM1 ;GET 1ST 3RD OF FILE NAME
PUSHJ P,C5T6 ;CONVERT TO SIXBIT
MOVSI P1,(T1) ;SAVE IT
LOAD. T1,FNM2 ;GET 2ND 3RD OF FILE NAME
PUSHJ P,C5T6 ;CONVERT TO SIXBIT
HRRI P1,(T1) ;COMBINE IT WITH 1ST 3RD
CAME P1,TMPFDB+.FXNAM ;SKIP IF FHB NAME MATCHS DIR NAME
TYPE <% FHB name doesn't match directory name
>
MOVE T1,.FXNAM+TMPFDB ;GET FILE NAME FROM FHB
TDZ T1,.FXNMM+OUTFDB ;AND EXTRACT CHARACTERS HE DIDN'T GIVE
;IN THE OUTPUT SPEC ON LEFT OF =
MOVE T2,.FXNAM+OUTFDB ;GET OUTPUT SPEC FROM LEFT OF =
AND T2,.FXNMM+OUTFDB ;KEEP ONLY NON WILD CHARACTERS
OR T1,T2 ;MERGE THE TWO FOR FINAL OUTPUT NAME
MOVEM T1,.FXNAM+TMPFDB ;RESSAVE OUTPUT FILE NAME
POPJ P,
;ROUTINE TO SETUP THE FILE TYPE DATA PRIOR TO THE ENTER
GE$TYP: LOAD. T1,FTYP ;GET FILE TYPE FROM FHB
PUSHJ P,C5T6 ;CONVERT TO SIXBIT
HLRZ T2,.FXEXT+TMPFDB ;GET FILE TYPE FROM DIRECTORY ENTRY
CAME T1,T2 ;SKIP IF FHB TYPE IS SAME AS DIR TYPE
TYPE <% FHB type doesn't match directory type
>
HRLZ T3,.FXEXT+OUTFDB ;GET WILD CARD MASK TO LEFT OF =
HLLZ T1,.FXEXT+TMPFDB ;GET FILE TYPE FROM DIRECTORY ENTRY
TDZ T1,T3 ;TURN OFF WILD CHARACTERS
HLLZ T2,.FXEXT+OUTFDB ;GET FILE TYPE FROM LEFT OF =
AND T2,T3 ;KEEP ONLY WILD CHARACTERS
OR T1,T2 ;MERGE THE TWO TOGETHER
HLLOM T1,.FXEXT+TMPFDB ;SAVE RECOMPUTED EXT NAME
POPJ P, ;RETURN TO CALLER
;ROUTINE TO SETUP THE OUTPUT SWITCHES FOR THE FILE IN A "GET" COMMAND
GE$SWT: HLRZ T1,.FXEXT+TMPFDB ;GET FILE TYPE FROM DIRECTORY
PUSHJ P,C6T5 ;CONVERT TO RAD50 FOR EXTCHK
PUSHJ P,EXTCHK ;GO CHECK AND SETUP FLAGS
;LEAVE RECOMMENDED SWITCHES IN T1
MOVE T2,.FXSWT(FP) ;GET INPUT SWITCHES
MOVE T3,.FXSWT+OUTFDB ;GET DEFAULT OUTPUT SWITCHES
TDNE T3,[S$IMAG!S$BINA!S$ASCI];DID HE GIVE AN ALL INCLUSIVE OUTPUT?
MOVE T1,T3 ;USE SWITCHES FROM INCLUSIVE OUTPUT
;RATHER THAN THOSE IMPLIED BY EXT
TDNE T2,[S$IMAG!S$BINA!S$ASCI];GIVE A SPEC ON THIS INPUT FFILE?
MOVE T1,T2 ;USE SWITCHES APPLIED SPECIFICALLY
;TO THIS FILE IN PLACE OF ANY OTHER
MOVEM T1,.FXSWT+TMPFDB ;SAVE THE ADJUSTED FLAGS
POPJ P,
;ROUTINE TO EXTRACT ASCII DATE FROM FHB
; AND INSERT IT INTO ENTER BLOCK FOR "GET" COMMAND
GE$CDT: MOVE T1,[O.CRDT,,A.CRDT] ;T1=BYTE POINTER TO CREATE DATE
MOVEI T2,FHBBUF ;OFFSET TO FHB TO ACCESS
PUSHJ P,REDDAT ;GO READ THE DATE FROM FHB
DPB T1,[POINT 12,LERBLK+.RBPRV,35] ;INSERT LO 12 BITS OF DEC10 DATE
LSH T1,^D-12 ;DUMP LOW 12 BITS
DPB T1,[POINT 3,LERBLK+.RBEXT,20] ;INSERT HI 3 BITS OF DEC10 DATE
MOVE T1,[O.CRTI,,A.CRTI] ;T1=BYTE POINTER TO CREATE TIME
MOVEI T2,FHBBUF ;T2=OFFSET TO FHB TO ACCESS
PUSHJ P,REDTIM ;GO READ THE TIME FROM FHB
DPB T1,[POINT 11,LERBLK+.RBPRV,23] ;INSERT TIME INTO LER BLOCK
POPJ P, ;RETURN TO CALLER
SUBTTL COMMANDS -- PUT
C$PUT: PUSHJ P,FILIN ;GET OUTPUT SPEX
SKIPN FP,IPLIST ;LOAD UP POINTER TO FILE LIST
PUSHJ P,ILLCMD
PUSHJ P,TTYPHY ;SETUP TTY:
SETZ T2, ;COUNT NUMBER OF OUTPUT FILE SPEX
C$PUT0: MOVE T1,[FX.EQL] ;= SEEN IN THIS SPEC
TDNE T1,.FXMOD(FP) ;SKIP IF INPUT SPEC
PUSHJ P,POCHEK ;RETURN IF OUTPUT SPEC LOOKS VALID
HRRZ FP,.FXLNK(FP) ;STEP TO NEXT FILE SPEC, IF ANY
JUMPN FP,C$PUT0 ;BRANCH IF ANY FILE SPEC
JUMPE T2,[PUSHJ P,ILLCMD] ;MUST BE AT LEAST 1 OUTPUT FILE
HRRZ FP,IPLIST ;LOAD UP POINTER TO START OF FILE LIST
PUSHJ P,C$PUTA ;GO DO A FILE SPEC
HRRZ FP,.FXLNK(FP) ;STEP TO NEXT FILE SPEC, IF ANY
JUMPN FP,.-2 ;LOOP IF ANOTHER FILE THERE
POPJ P, ;DONE IF NO MORE
;ROUTINE TO LOOK AT OUTPUT SPEC TO DETERMINE VALIDITY
POCHEK: SETO T1, ;NO WILD CHARS PLEASE
CAMN T1,.FXDNM(FP) ;SKIP IF WILD CHARS
CAME T1,.F2DNM(FP) ;SKIP IF NO WILD CHARS
JSP U0,ILLPPN ;GO COMPLAIN
SKIPE .FXDIR+2(FP) ;SKIP IF NO SFD LIST
JSP U0,ILLPPN
AOJA T2,CPOPJ
; COME HERE WITH A POSSIBLY WILD INPUT SPEC AT (FP)
C$PUTA: PUSHJ P,SAVFF ;SAVE .JBFF
PUSHJ P,SETOUT ;SETUP THE OUTPUT FDB (GOING TO 20F DISK)
PUSHJ P,SAVFP ;SAVE FP
MOVEM FP,FPCOPY ;SAVE FP
MOVEI FP,OUTFDB ;POINT AT OUTPUT FDB
PUSHJ P,OPNVOL ;OPEN THAT VOLUME
SETZM FPWILD ;INIT FILE POINTER THAT WILD USES
$PUTA0: MOVSI T1,'DSK'
SKIPN @FPCOPY
MOVEM T1,@FPCOPY ;THIS DEPENDS ON .FXDEV=0
MOVE T1,[XWD 5,[XWD FPCOPY,0 ; FPCOPY=POINTER TO CURRENT SPEC
XWD OPNBLK,LERBLK; OPENBLOCK,,LOOKUP BLOCK
XWD .FXLEN,177; FDB LENGTH,,LER LENGTH
XWD <(1B0)>!WLD,FPWILD
0]] ;
PUSHJ P,.LKWLD## ;EXPAND FILE SPEC
POPJ P, ;ALL DONE
PUSHJ P,C$PUTB ;GO XFER THE FILE WE FOUND
POPJ P, ;HERE IF NO POINT IN CONTINUING WITH THIS FDB
JRST $PUTA0 ;LOOP FINDING FILES
; HERE WHEN WE FIND AN INPUT FILE TO COPY TO THE 20F DISK
; COMPUTE NAME AS IT WILL APPEAR ON THE 20F DISK
C$PUTB: PUSHJ P,SAVFF ;SAVE .JBFF, WE MIGHT EXPAND DURING I/O
TDZ F,[X%SUPER] ;NOT SUPERCEEDING (YET)
SETZM TMPFDB
SETZM BLKCNT
MOVE T1,[TMPFDB,,TMPFDB+1]
BLT T1,TMPFDB+.FXLEN-1
MOVE T1,LERBLK+.RBNAM ;GET THE FILE NAME ON PDP10 DISK
TDZ T1,OUTFDB+.FXNMM ;KEEP THE OUTPUT FILE'S WILD CHARACTERS
MOVE T2,OUTFDB+.FXNAM ;GET THE FILE NAME ON 20F DISK
AND T2,OUTFDB+.FXNMM ;TURN OFF THE WILD CHARACTERS
IOR T1,T2 ;COMPUTE FINAL NAME
MOVEM T1,TMPFDB+.FXNAM ;SAVE THE FINAL NAME
MOVE T1,OUTFDB+.F2NAM ;GET 2ND HALF OF OUTPUT NAME
MOVEM T1,TMPFDB+.F2NAM ;SPECIFY 2ND HALF OF OUTPUT NAME
HLRZ T1,LERBLK+.RBEXT ;GET FILE TYPE ON PDP10 DISK
TDZ T1,OUTFDB+.FXEXT ;KEEP OUTPUT FILE'S WILD CHARACTERS
HLRZ T2,OUTFDB+.FXEXT ;GET FILE TYPE ON 20F DISK
AND T2,OUTFDB+.FXEXT ;TURN OFF THE WILD CHARACTERS
IOR T1,T2 ;MERGE AND COMPUTE FINAL TYPE
HRLOM T1,TMPFDB+.FXEXT ;SPECIFY FILE TYPE
DMOVE T1,OUTFDB+.FXDIN ;GET DIRECTORY SPEC
DMOVEM T1,TMPFDB+.FXDIN ;STORE IT
SETOM TMPFDB+.FXDNM ;MAKE DIRECTORY FULLY SPECIFIED
SETOM TMPFDB+.F2DNM ;MAKE DIRECTORY FULLY SPECIFIED
SETOM TMPFDB+.FXNMM ;MAKE FILE NAME FULLY SPECIFIED
SETOM TMPFDB+.F2NMM ;MAKE .....
; FIND INPUT FILE
MOVE T1,[UU.PHS!.IOASC] ;BY DEFAULT, USE ASCII MODE
MOVE T1,OPNBLK+0 ;...
MOVEI T1,DIBUF ;BY DEFAULT, USE DISK INPUT BUFFER
MOVEM T1,OPNBLK+2 ;...
OPEN FIO,OPNBLK ;OPEN INPUT DISK FOR INPUT
JRST PUTER4 ;COMPLAIN IF DEVICE DISAPPEARED
LOOKUP FIO,LERBLK ;FIND INPUT FILE
JRST PUTER5 ;GO COMPLAIN IF YOU CAN'T
SKIPN T1,OUTFDB+.FXGEN ;SKIP IF HE GAVE EXPLICIT VERSION #
HRRZ T1,LERBLK+.RBVER ;FETCH EDIT # IF GIVEN ON FILE RIB
ANDI T1,77777 ;TRUNCATE VERSION NUMBER TO 15 BITS
MOVEM T1,TMPFDB+.FXGEN ;REMEMBER VERSION NUMBER FOR OUTPUT
; SCAN THE SPECIFIED 20F DIRECTORY FOR THE PROPER SPOT TO INSERT THIS FILE.
; IF THE CORRECT FILE/GENERATION ALREADY EXISTS, PREPARE TO SUPERCEED IT.
; IF THE FILE IS BRAND NEW, FIND A NULL ENTRY AND INSERT THE FILE THERE.
; IF THE DIRECTORY IS FULL, EXPAND BY A BLOCK AND INSERT THE FILE THERE.
PUSHJ P,RLDINI ;INITIALIZE 20F WILD CARD INTERFACE
SETO P4, ;P4=BEST GENERATION NUMBER
$PUTB1: MOVEI T1,TMPFDB ;GET FDB WITH FULLY SPECIFIED FILE
MOVEI T2,FAKFDB ;GET AN FDB TO OUTPUT TO
PUSHJ P,NXTFDB ;SEARCH 20F DISK FOR OLD VERSION OF FILE
JRST $PUTB2 ;BRANCH IF NO MORE FILES
CAMGE P4,.FXGEN+FAKFDB ;IS GENERATION HIGHER THAN BEST SO FAR?
MOVE P4,.FXGEN+FAKFDB ;KEEP HIGHEST GEN# IN P4
SKIPE T1,TMPFDB+.FXGEN ;SKIP IF NO EXPLICIT GENERATION #
CAME T1,FAKFDB+.FXGEN ;SKIP IF EXPLICIT AND THEY MATCH TOO
JRST $PUTB1 ;LOOP IF NOT THE RIGHT FILE
MOVE T1,.FXNUM+FAKFDB ;GET FILE # OF MATCHING FILE
MOVEM T1,.FXNUM+TMPFDB ;AND REMEMBER IT
TDO F,[X%SUPER] ;FILE IS BEING SUPERCEEDED
MOVEI T2,DELBUF ;WHERE TO GET OLD FHB
PUSHJ P,REDFHB ;READ IN OLD FHB
JRST $PUTB3 ;YES, USE THIS SLOT
; HERE WHEN NXTFDB HAS SCANNED ALL OF THE DIRECTORY AND HAS NOT FOUND
; AN EXPLICIT MATCHING FILE TO SUPERCEED. NOW SCAN THE SAME DIRECTORY
; FOR A NULL SLOT WE CAN USE TO INSERT THIS NEW FILE.
$PUTB2: MOVE T1,DIRMAT ;GET # OF DIRECTORIES SCANNED
CAIE T1,1 ;000000.DIR AND OUR DIR
JRST PUTER1 ;GO MENTION ERROR AND ABORT
PUSHJ P,RLDINI ;INITIALIZE WILD CARDER
DMOVE T1,OUTFDB+.FXDIN ;GET DIRECTORY WE WANT
DMOVEM T1,NULFDB+.FXDIN ;SAVE DIRECTORY WE WANT IN NULL FDB
MOVEI T1,NULFDB ;EXPLICIT FDB OF 0S
MOVEI T2,FAKFDB ;FDB TO EXPAND INTO
PUSHJ P,NXTFDB ;FIND AN EMPTY SLOT
JRST UFDGRO ;GROW THE UFD 1 BLOCK AND TRY AGAIN
CAIN P4,177777 ;SKIP IF WE HAVEN'T RUN OUT OF VERSIONS
JRST PUTER3 ;COMPLAIN IF NO VERSION #S LEFT
AOSN P4 ;INCREMENT TO NEXT HIGHEST GENERATION
HRRZ P4,TMPFDB+.FXGEN ;GET GENERATION
ANDI P4,177777 ;ONLY KEEP LOW ORDER BITS
CAIN P4,0 ;CHECK FOR OVERFLOW
MOVEI P4,1 ;AND CONVERT TO VERSION#1 IF SO
MOVEM P4,TMPFDB+.FXGEN ;SAVE GENERATION NUMBER
MOVE T1,IPLIST ;POINT AT FIRST FILE BLOCK
MOVE T1,V$FILE(T1) ;GET /FILE SWITCH ON OUTPUT FILE
PUSHJ P,ALCFHB ;GO GET A FILE NUMBER
MOVEM T1,TMPFDB+.FXNUM ;AND REMEMBER IT FOR LATER
; HERE WHEN WE KNOW WHERE IN THE DIRECTORY WE WANT TO INSERT THIS FILE.
$PUTB3: MOVNI T1,.DIROFF ;OFFSET TO MATCHING SLOT
ADDM T1,WDIOFF ;ADJUST POINTER TO POINT AT MATCH
MOVEI T1,<TMPBUF-FHBBUF>*4 ;GET OFFSET FOR OUR FHB
MOVEM T1,FHBFOO ;SAVE IT
;NOW, "FHBFOO" IS AN OFFSET STYLE POINTER INTO THE FHB WE'RE BUILDING
;AND "WDIOFF" IS AN OFFSET POINTER INTO THE SLOT IN THE DIRECTORY WE'RE USING.
MOVE T1,TMPFDB+.FXNUM ;GET DESIRED FILE #
STOR. T1,UFNO,WDIOFF ;STORE FILE # INTO DIRECTORY
MOVEI T2,TMPBUF ;GET FHB ADDRESS
PUSHJ P,INIFHB ;CREATE THE INITIAL FHB FOR ME
LOAD. T1,FSEQ,FHBFOO ;GET THE NEW SEQ #
STOR. T1,UFSQ,WDIOFF ;STORE SEQ# IN DIRECTORY
HLRZ T1,TMPFDB+.FXNAM ;GET SIXBIT NAME 1ST 3RD
PUSHJ P,C6T5 ;CONVERT 1ST 3RD TO RAD50
STOR. T1,FNM1,FHBFOO ;STORE FILE NAME PART 1 INTO FHB
STOR. T1,UFN1,WDIOFF ;INSERT INTO DIRECTORY TOO
HRRZ T1,TMPFDB+.FXNAM ;GET SIXBIT NAME PART 2
PUSHJ P,C6T5 ;CONVERT 2ND 3RD TO RAD50
STOR. T1,FNM2,FHBFOO ;STORE FILE NAME PART 2 IN FHB
STOR. T1,UFN2,WDIOFF ;INSERT INTO DIRECTORY TOO
HLRZ T1,TMPFDB+.F2NAM ;GET 3RD PART OF FILE NAME
PUSHJ P,C6T5 ;CONVERT TO RAD50
STOR. T1,FNM3,FHBFOO ;PUT INTO FHB
STOR. T1,UFN3,WDIOFF ;PUT INTO DIRECTORY FILE TOO
HLRZ T1,TMPFDB+.FXEXT ;GET FILE TYPE
PUSHJ P,C6T5 ;CONVERT TO RAD50
STOR. T1,FTYP,FHBFOO ;STORE INTO FHB
STOR. T1,UFTY,WDIOFF ;STORE INTO DIRECTORY TOO
MOVE T1,.FXGEN+TMPFDB ;GET GENERATION #
STOR. T1,UVER,WDIOFF ;STORE INTO DIRECTORY
STOR. T1,FVER,FHBFOO ;AND STORE INTO FHB
SKIPE T1,V$FPRO+OUTFDB
STOR. T1,FPRO,FHBFOO ;STORE PROTECTION IF SPECIFIED
;HERE TO SETUP AND PREPARE FOR ACTUAL TRANSFER OF DATA
LOAD. T1,FTYP,FHBFOO ;GET THE FILE TYPE IN RAD50
PUSHJ P,EXTCHK ;GO IMPLY SOME FLAGS
MOVE T2,.FXSWT+OUTFDB ;GET OUTPUT SWITCHES
TDZ T2,[S$IMAG!S$BINA!S$ASCI!S$CONT];FORGET MODE FLAGS
MOVE T3,.FXSWT+OUTFDB ;GET OUTPUT SWITCHES
TDNE T3,[S$IMAG!S$BINA!S$ASCI!S$CONT];GIVE AN OUTPUT SWITCH?
MOVE T1,T3 ;YES, GET MODE FLAGS FROM THAT
AND T1,[S$IMAG!S$BINA!S$ASCI!S$CONT];ISOLATE MODE SWITCHES ONLY
OR T1,T2 ;MIX UP ALL THE FLAGS
TDNN T1,[S$IMAG!S$BINA!S$ASCI]
TDO T1,[S$ASCI] ;FORCE /ASCII IF NOTHING ELSE
MOVEM T1,TMPFDB+.FXSWT ;GO TURN ON THE SWITCHES, IF ANY
SETZM CHULFT ;0 LEFT IN CURRENT CHUNK
SETZM STOLFT ;0 LEFT IN CURRENT STORAGE POINTER
TDZ F,[X%FIR!X%EOF] ;NO I/O YET, THEREFORE NO EOF YET
MOVE T1,[O.CRDT,,A.CRDT] ;SETUP PDP11 BYTE POINTER TO CREATE DATE
MOVEI T2,TMPBUF ;POINT AT OUTPUT FILE'S FHB
LDB T4,[POINT 3,LERBLK+.RBEXT,20] ;FETCH PDP10'S CREATE DATE
LSH T4,^D12 ;MAKE ROOM FOR MORE BITS
LDB T3,[POINT 12,LERBLK+.RBPRV,35] ;GET LOW ORDER PDP10 DATE
OR T3,T4 ;COMPUTE PDP10 CREATE DATE
PUSHJ P,STODAT ;INSERT CREATE DATE INTO FHB
MOVE T1,[O.CRTI,,A.CRTI] ;GET PDP11 BYTE POINTER TO CREATE TIME
MOVEI T2,TMPBUF ;GET POINTER TO OUTPUT FILE'S FHB
LDB T3,[POINT 11,LERBLK+.RBPRV,23] ;GET CREATE TIME FROM RIB
PUSHJ P,STOTIM ;STORE CREATE TIME INTO FHB
MOVE T1,TMPFDB+.FXSWT ;GET OUTPUT MODE FLAGS
TDNN T1,[S$IMAG!S$BINA]
JRST C$PUTC ;DO ASCI MODE XFER TO RSX20F
JRST C$PUTD ;DO IMAGE MODE XFER TO 20F
;ROUTINE TO GROW THE UFD BY ONE BLOCK TO MAKE ROOM FOR MORE FILES
UFDGRO: TYPE <% Expanding User File Directory>
PUSHJ P,CRLF
MOVEI T1,WDIFHB ;POINT AT THE FHB
PUSHJ P,EXPDIR ;EXPAND T
JRST PUTER2 ;GO COMPLAIN
JRST $PUTB2 ;GO SCAN NEW UFD BLOCK FOR 0S
SUBTTL EXPDIR
; ROUTINE TO EXPAND THE UFD WHOSE FHB IS (T1)
;
;ENTER:
; T1/ ADDRESS OF FHB
;EXIT:
; <nonskip - we failed>
; <skip - we expanded by 1 block>
EXPDIR: PUSHJ P,SAVE4 ;SAVE SOME ACS
MOVE P1,T1 ;SAVE THE FHB ADDRESS
MOVEI T1,1 ;SPECIFY A MAX OF 1 BLOCK NEEDED
PUSHJ P,SCNSBM ;
JRST EXPER0 ;GO COMPLAIN
MOVEI T1,1 ;ONLY USE 1 BLOCK, NO MATTER HOW MANY
MOVE P2,T2 ;REMEMBER THE BLOCK WE GOT
MOVEI T3,(P1) ;POINT AT THE FHB CONVERNED
PUSHJ P,STORET ;INSERT RIB POINTER FOR NEW BLOCK
MOVE P4,P1 ;COPY ADDRESS OF FHB
SUBI P4,FHBBUF ;GET PDP10 OFFSET BETWEEN FHB BUFFRS
IMULI P4,4 ;COMPUTE # PDP11 BYTES IN OFFSET
LOAD. T1,HIBL,P4 ;GET # OF HI BLOCK (LOW)
ADDI T1,1 ;ONE MORE BLOCK WAS ADDED
STOR. T1,HIBL,P4 ;PUT IT BACK
LOAD. T2,HIBH,P4 ;GET HIGH PART OF HI BLOK#
ADDI T2,1 ;PRETEND A CARRY TOOK PLACE
TRNE T1,200000 ;SKIP IF CARRY DIDN'T
STOR. T2,HIBH,P4 ;UPDATE HIGH PART IF CARRY HAPPENED
LOAD. T1,EFBL,P4 ;GET # OF EOF BLOCK (LOW)
ADDI T1,1 ;ONE MORE BLOCK ADDED
STOR. T1,EFBL,P4 ;INSERT INC'ED BLOCK #
LOAD. T2,EFBH,P4 ;GET HGH #
ADDI T2,1 ;ASSUME CARRY OCCURRED
TRNE T1,200000 ;SKIP IFF CARRY DID NOT HAPPPEN
STOR. T2,EFBH,P4 ;INSERT HGH ORDER IF CARRY HAPPENED
MOVE T1,P1 ;T1=ADDR OF FHB
PUSHJ P,WRUFHB ;GO (RE)WRITE THE FHB
MOVE T1,P2 ;GET BACK THE NEWLY ALLOCATED BLOCK #
PUSHJ P,SUSET ;POSITION THE DISK TO THAT BLOCK
OUTPUT VIO,[IOWD 1,LOWZRO ;ZERO THE NEW BLOCK
0] ;...
JRST CPOPJ1
EXPER0: TYPE <% Cannot extend directory
>
POPJ P,
;
; VARIOUS RANDOM OUTPUT ERRORS FOR PUT COMMAND
; HERE IF OUTPUT DIRECTORY FOR "PUT" COMMAND DOESN'T EXIST OR
; IF (HOW?) THERE IS MORE THAN 1 DIRECTORY
PUTER1: TYPE <% Output directory does not exist for >
PUTER0: PUSHJ P,VOLOUT ;TYPE NAME OF VOLUME
DMOVE T1,OUTFDB+.FXDIN ;GET DIRECTORY
PUSHJ P,TYPDIN ;TYPE DIRECTORY
MOVE T1,TMPFDB+.FXNAM ;GET FILE NAME
PUSHJ P,SIXOUT ;TYPE 1ST PART OF FILE NAME
SKIPE T1,TMPFDB+.F2NAME ;GET 2ND PART OF FILE NAME
PUSHJ P,SIXOUT ;TYPE 2ND PART OF FILE NAME
TYPE <.> ;SEPERAT
HLLZ T1,TMPFDB+.FXEXT ;GET EXTENSION
PUSHJ P,SIXOUT ;TYPE FILENAME EXTENSION
PJRST CRLF ;AND EXIT
PUTER2: TYPE <% Cannot extend directory for >
JRST PUTER0
PUTER3: TYPE <% All generation numbers already used for >
AOS (P)
JRST PUTER0
PUTER4: TYPE <% Cannot OPEN input device for >
PUSHJ P,PUTR4B
PUSHJ P,CRLF
JRST CPOPJ1
PUTR4B: SKIPN T1,OPNBLK+1 ;GET DEVICE NAME
MOVSI T1,'???' ;GET ERROR DEVICE NAME
PUSHJ P,SIXOUT ;TYPE DEVICE NAME
TYPE <:> ;TRAIL WITH SEPERATOR
MOVE T1,LERBLK+.RBNAM ;GET FILE NAME FROM RIB
PUSHJ P,SIXOUT ;TYPE FILE NAME
TYPE <.> ;DOT SEPERATOR FOR FILENAME EXTENSION
HLLZ T1,LERBLK+.RBEXT ;GET FILENAME EXTESION FROM RIB
SKIPE T1 ;SKIP IF BLANK EXTENSION
PUSHJ P,SIXOUT ;TYPE OUT FILENAME EXTENSION
PJRST TYPPTH ;TYPE OUT PATH SPEC
PUTER5: TYPE <% LOOKUP error >
HRRZ T1,LERBLK+.RBEXT ;GET LOOKUP ERROR FROM L/E/R BLOCK
PUSHJ P,OCTOUT ;TYPE ERROR NUMBER IN OCTAL
TYPE < for > ;
PUSHJ P,PUTR4B ;TYPE FILENAME.TYPE
PUSHJ P,CRLF ;END WITH CRLF
JRST CPOPJ1
;HERE TO XFER AN IMAGE MODE FILE
C$PUTD: SETZM STOCNT ;NO BLOCKS IN FIRST RET POINTER
STOR. [R.FIX],RTYP,FHBFOO ;SHOW FIXED TYPE RECORDS
STOR. [^D512],RSIZ,FHBFOO ;FIXED LENGTH IS 512 BYTES=1 DISK BLOK
; ^^^ THIS IS THE PLACE TO SETUP OTHER RANDOM FHB VALUES!
SETSTS FIO,.IOIMG ;OVERRIDE ASCII, USE IMAGE MODE
MOVSI T1,(POINT 36,0,35) ;GET IMAGE MODE BYTE POINTER
HLLM T1,DIBUF+.BFPTR ;SO CALCULATIONS BELOW COME OUT RIGHT
;HERE TO READ ANOTHER BLOCK
$PUTD1: IN FIO, ;READ BLOCK FROM 10 DISK
SKIPA
JRST $PUTD2 ;BRANCH IF INPUT FROM TOPS10 FAILED
$PUTD3: HRRZ T1,DIBUF+.BFCTR ;GET PDP10 WORD COUNT
IMULI T1,4 ;CONVERT TO PDP11 BYTE COUNT
MOVNS T1 ;MAKE IT -VE
ADDI T1,1000 ;COMPUTE RSX COUNT
MOVEM T1,RSXCTR ;SAVE RSX COUNT FOR OUT20F
HRRZ T1,DIBUF+.BFPTR ;POINT AT BUFFER
ADDI T1,1 ;POINT AT DATA PORTION
PUSHJ P,OUT20F ;OUTPUT THAT BLOCK
JRST $PUTD1 ;LOOP
;HERE IF ERROR READING TOPS10 FILE
$PUTD2: STATZ FIO,IO.ERR ;SKIP IF JUST AN EOF ERROR
JRST $PUTD4 ;BRANCH IF REAL SERIOS ERROR
JRST PTIEOF ;JOIN COMMON EOF PROCESSOR
$PUTD4: TYPE <% Input error > ;HERALD THE ERROR
GETSTS FIO,T1 ;GET I/O STATUS FOR THAT CHANNEL
PUSHJ P,OCTOUT ;TYPE THE STATUS
TYPE < for > ;
PUSHJ P,PUTR4B ;TYPE FILE SPEC
TYPE <, block >
MOVE T1,BLKCNT ;GET RELATIVE BLOCK NUMBER
PUSHJ P,DECOUT ;TYPE RELATIVE BLOCK # IN DECIMAL
PUSHJ P,CRLF ;END MESG WITH CRLF
GETSTS FIO,T1 ;GET STATUS AGAIN
TDZ T1,[IO.ERR] ;TURN OFF ANY ERROR BITS
SETSTS FIO,(T1) ;FORCE ERROR-FREE STATUS TO TAKE EFFECT
JRST $PUTD3 ;GO OUTPUT BLOCK ANYWAY TO PRESERVE SIZE
;ROUTINE TO WRITE A BLOCK TO THE OUTPUT FILE
OUT20F: TDZE F,[X%FIR] ;SKIP IF NOT FIRST XFER
POPJ P, ;RETURN IMMEDIATELY IF FIRST XFER
PUSHJ P,SAVE1 ;SAVE P1
MOVEI P1,(T1) ;COPY BUFFER ADDRESS
OUT20: SOSGE STOLFT ;SKIP IF MORE BLOCKS LEFT IN POINTER
JRST OUT20A ;BRANCH IF POINTER FULL
HRLI T1,-200 ;INSERT A WORD COUNT INTO IOWD
HRRI T1,-1(P1) ;CONSTRUCT IOWD STYLE ADDRESS
SETZ T2, ;FINISH IOWD LIST
OUT VIO,T1 ;WRITE A BLOCK
AOSA T1,BLKCNT ;COUNT A GOOD BLOCK IN OUTPUT
JRST OUT22F ;GO ANNOUNCE OUTPUT ERROR
STOR. BLKCNT,HIBL,FHBFOO ;KEEP TRACK OF LO VBN IN FHB
LSH T1,^D-16 ;ISOLATE THE HIGH PART
STOR. T1,HIBH,FHBFOO ;KEEP TRACK OF HI VBN IN FHB
SOS CHULFT ;ONE LESS IN THE CHUNK
AOS CHULBN ;REMAINDER OF CHUNKS STARTS 1 LATER
AOS STOCNT ;1 MORE BLOCK IN RET POINTER
POPJ P,
;HERE IF WE JUST RAN OUT OF SPACE IN THE POINTER
OUT20A: SKIPN BLKCNT ;SKIP IF NOT VERY FIRST TIME
JRST OUT20B ;VERY FIRST TIME.
PUSH P,T3 ;T3 MAY HAVE ASCII BYTE IN IT
MOVE T1,STOCNT ;GET ACTUAL COUNT OF BLOCKS IN POINTER
MOVE T2,STOLBN ;GET ACTUAL BASE LBN FOR POINTER
MOVEI T3,TMPBUF ;POINT AT OUTPUT FILE'S FHB
PUSHJ P,STORET ;SAVE THE RETRIEVAL POINTER IN FHB
POP P,T3
;HERE IF WE DIDN'T HAVE A RETREIVAL POINTER TO STORE
OUT20B: SKIPN T1,CHULFT ;SKIP IF MORE SPACE IN CHUNK
JRST OUT20C ;BRANCH IF TIME TO ALLOCATE NEW CHUNK
CAILE T1,^D256 ;SKIP IF 256 OR LESS
MOVEI T1,^D256 ;DON'T LET MORE THAN 256 INTO A POINTER
MOVEM T1,STOLFT ;START A NEW POINTER
SETZM STOCNT ;NO BLOCKS IN POINTER YET
MOVE T1,CHULBN ;GET BASE OF REMAINDER OF CHUNK
MOVEM T1,STOLBN ;MAKE IT BASE OF FUTURE POINTER
JRST OUT20 ;LOOP TO TRY OUTPUT AGAIN
;HERE IF WE HAVEN'T ANY MORE SPACE AT ALL - ALLOCATE NEW CHUNK
OUT20C: MOVE T1,LERBLK+.RBALC ;GET # OF BLOCKS WE NEED
PUSHJ P,SCNSBM ;GET THOSE BLOCKS WE WANTED
JRST OUT20D ;BRANCH IF VOLUME COMPLETELY FULL
MOVEM T1,CHULFT ;SAVE # OF BLOCKS IN NEW CHUNK
MOVEM T2,CHULBN ;SAVE # OF FIRST BLOCK IN CHUNK
MOVNS T1 ;GET -VE # OF BLOCKS ALLOCATED
ADDM T1,LERBLK+.RBALC ;REMEMBER # OF BLOCKS STILL NEEDED
MOVE T1,CHULBN ;POSITION TO BEGINNING
PUSHJ P,SUSET ;POINT AT THAT BLOCK
JRST OUT20 ;LOOP TO TRY OUTPUT AGAIN
;HERE IF WE'RE COMPLETELY OUT OF SPACE IN THE VOLUME
OUT20D: TYPE <? Volume out of free space>,OUT23F
OUT22F: TYPE <% Output error >
GETSTS VIO,T1 ;GET I/O STATUS
PUSHJ P,OCTOUT ;TYPE I/O STATUS IN OCTAL
OUT23F: TYPE < for > ;PREFACE FILE SPEC
PUSHJ P,PUTER0 ;GIVE FILE SPEC
TYPE <, file block >
MOVE T1,BLKCNT
PUSHJ P,DECOUT ;ANNOUNCE BLOCK NUMBER
PUSHJ P,CRLF ;GIVE CRLF
JRST .ERR ;AND THEN ABORT
;HERE TO XFER AN ASCII MODE FILE
C$PUTC: SETOM RSXCTR ;START OFF BUFFERED POINTER
SETZM STOCNT ;NO BLOCKS IN FIRST RET POINTER
TDO F,[X%FIR] ;FIRST XFER (FORCE "DUMMY" OUTPUT)
STOR. [R.VAR],RTYP,FHBFOO ;VARIABLE LENGTH RECORDS
STOR. [FD.CR],RATT,FHBFOO ;CR/LF PAIRS IMPLIED
INPUT FIO, ;READ A BLOCK
STATZ FIO,IO.EOF!IO.ERR ;EOF OR ERROR?
JRST $PUTC1 ;YES, GO HANDLE THAT
TDZ F,[X%SEQ] ;CLEAR SEQ FILE BIT
MOVE T1,DIBUF+.BFPTR ;GET THE POINTER
IBP T1 ;MAKE SURE IT'S VALID
MOVE T1,(T1) ;GET THE 1ST WORD OF THE FILE
TRNE T1,1B35 ;LINE # BIT ON?
TDO F,[X%SEQ] ;REMEMBER THIS IS A SEQ FILE
MOVE T1,LERBLK+.RBALC ;GET # OF PDP10 BLOCKS
IMULI T1,5 ;COMPUTE # OF PDP10 TEXT BYTES
IDIVI T1,4 ;COMPUTE # OF PDP11 BLOCKS NEEDED
MOVEM T1,LERBLK+.RBALC ;SAVE # OF PDP11 BLOCKS
IDIVI T1,<200/^D80> ;COMPUTE # OF "LINES" INVOLVED
IMULI T1,2 ;ADD IN THE COUNT BYTES
TDNE F,[X%SEQ] ;SKIP IF NOT A LINE-SEQUENCED FILE
IMULI T1,2 ;ADD IN THE SEQUENCE BYTES
IDIVI T1,1000 ;COMPUTE # OF BLOCKS ADDITIONAL NEEDED
ADDI T1,1 ;ONE MORE
ADDM T1,LERBLK+.RBALC ;ESTIMATE # BLOCKS NEEDED TOTAL
SETZM LINSIZ ;MAX LINE SIZE SEEN WAS 0 BYTES
TDZE F,[X%SEQ] ;SKIP IF REGULAR FILE
JRST C$PUTE ;COPY A SEQUENCED FILE
JRST C$PUTF ;COPY A VARIABLE FILE
$PUTC1: STATO FIO,IO.EOF ;SKIP IF EOF (IE: NULL FILE)
ERROR <I/O error on input file>
JRST PTAEOF ;ODD, NULL FILE
;HERE TO XFER A NORMAL ASCII MODE FILE
C$PUTF: MOVSI P1,-<1000*5-1> ;COUNT OF MAX CHARACTERS PER LINE
MOVE P2,[POINT 7,LINBUF] ;POINT AT LINE BUFFER
TDZE F,[X%FF] ;SKIP IF NO PENDING FF
JRST $PUTF5 ; BRANCH IF A FF IS PENDING
$PUTF1: JSP T4,GETC ;GET A BYTE
JRST [TDO F,[X%EOF] ;REMEMBER EOF
TRNN P1,-1 ;SKIP SOME CHARACTER SEEN
JRST PTAEOF ;BRANCH IF NO LAST LINE
JRST $PUTF2] ;SKIP AHEAD
CAILE T3,15 ;SKIP IF POSSIBLE CONTROL CHARACTER
$PUTF6: AOBJN P1,[IDPB T3,P2 ;LOOP IF STILL ROOM, INSERT CHARACTER
JRST $PUTF1] ;...
JUMPGE P1,$PUTF0 ;BRANCH IF OUT OF LINE BUFFER SPACE
CAIN T3,15 ;SKIP IF NOT CR
JRST $PUTF1 ;BRANCH TO IGNORE CR'S
CAIN T3,12 ;SKIP IF NOT LF
JRST $PUTF0 ;BRANCH TO TERMINATE LINE, IF LF
JUMPE T3,$PUTF1 ;BRANCH TO IGNORE NULL CHARACTERS
CAIE T3,14 ;SKIP IF FORM FEED
JRST $PUTF6 ;BRANCH IF JUST RANDOM CONTROL CHARATER
TDO F,[X%FF] ;TURN ON FF FLAG IF FORM FEED SEEN
$PUTF0: HRRZS P1 ;ISOLATE CHARACTER COUNT
;HERE IF WE FIND END OF LINE
$PUTF2: PUSH P,P1 ;SAVE BYTE COUNT
MOVE T3,(P) ;GET LOW BYTE
JSP T4,PUT20F ;SAVE LOW BYTE OF COUNT IN 20F FILE
LDB T3,[POINT 8,P1,27] ;GET HIGH BYTE OF COUNT
JSP T4,PUT20F ;SAVE HIGH BYTE TOO
MOVE P2,[POINT 7,LINBUF] ;GET POINTER
HRRZ P1,(P) ;RESTORE P1
JUMPE P1,$PUTF4 ;SKIP XFER OF BYTES IF NONE THERE
$PUTF3: ILDB T3,P2 ;GET A BYTE
JSP T4,PUT20F ;PUT BYTE IN 20F FILE
SOJG P1,$PUTF3 ;LOOP TILL LINE XFERRED
$PUTF4: POP P,P1 ;RESTORE BYTE COUNT
MOVEI T3,0
TRNE P1,1
JSP T4,PUT20F ;INSERT DUMMY IF ODD BYTE COUNT
CAMLE P1,LINSIZ ;SKIP IF LINE NOT ANY BIGGER THAN OTHERS
HRRZM P1,LINSIZ ;REMEBER BIGGEST LINE SIZE
TDZN F,[X%EOF] ;SKIP IF END OF FILE
JRST C$PUTF ;GO GET ANOTHER LINE
JRST PTAEOF ;JOIN COMMON CLOSE FILE CODE
;HERE IF WE ARE DEFERRING A FF
$PUTF5: MOVEI T3,14 ;GET A FF CHARACTER
AOBJN P1,.+1 ;COUNT IT
IDPB T3,P2 ;INSERT THE FF INTO THE LINE
JRST $PUTF0 ;AND END THIS LINE WITH ONLY FF ON IT
;HERE TO XFER A LINE SEQUENCED ASCII MODE FILE
C$PUTE: SETOM LINNUM ;ZERO LINE SEQ #
STOR. [R.SEQ],RTYP,FHBFOO ;DECLARE A SEQ'D FILE
$PUTE0: SETZ T1, ;ZERO COUNT OF CHARACTERS IN THIS LINE
MOVE T2,[POINT 7,LINBUF] ;POINT AT LINE BUFFER
$PUTE1: JSP T4,GETC ;GET A BYTE
JRST [TDO F,[X%EOF] ;REMEMBER EOF
JRST $PUTE2] ;SKIP AHEAD
MOVE T4,DIBUF+.BFPTR ;GET POINTER
MOVE T4,(T4) ;GET THE 5 CHARS THERE
TRNE T4,1 ;CHECK FOR START OF A NEW LINE
JRST $PUTE2 ;GO GET LINE NUMBER, FLUSH OLD ONE
JUMPE T3,$PUTE1 ;IGNORE NULLS
IDPB T3,T2 ;STORE THE BYTE WE JUST GOT
AOJA T1,$PUTE1 ;LOOP TILL END OF LINE
;HERE IF WE FIND A LINE SEQ# FLAG
$PUTE2: SKIPGE LINNUM ;SKIP IF NOT FIRST TIME
JRST $PUTE4 ;BRANCH IF FIRST TIME
;HERE IF WE FIND END OF LINE
ADDI T1,2 ;ACCOUNT FOR THE SEQ# BYTES
PUSH P,T1 ;SAVE BYTE COUNT
MOVE T3,T1 ;GET LOW BYTE OF COUNT
JSP T4,PUT20F ;SAVE LOW BYTE OF COUNT IN 20F FILE
LDB T3,[POINT 8,(P),27] ;GET HIGH BYTE OF COUNT
JSP T4,PUT20F ;SAVE HIGH BYTE TOO
MOVE T3,LINNUM ;GET LOW BYTE OF SEQ#
JSP T4,PUT20F ;PUT HIGH BYTE OF COUNT IN FILE
LDB T3,[POINT 8,LINNUM,27] ;GET HIGH BYTE OF SEQ#
JSP T4,PUT20F ;PUT HIGH BYTE IN 20F FILE
MOVE T1,(P) ;RESTORE BYTE COUNT
SUBI T1,2 ;DISCOUNT THE SEQ# BYTES
MOVE T2,[POINT 7,LINBUF] ;GET POINTER
$PUTE3: ILDB T3,T2 ;GET A BYTE
JSP T4,PUT20F ;PUT BYTE IN 20F FILE
SOJG T1,$PUTE3 ;LOOP TILL LINE XFERRED
POP P,T1 ;RESTORE BYTE COUNT
TRNE T1,1
JSP T4,PUT20F ;INSERT DUMMY IF ODD BYTE COUNT
TDZE F,[X%EOF] ;SKIP IF NOT END OF FILE
JRST PTAEOF ;CLOSE UP FILE, START ANOTHER
;HERE TO START A NEW LINE STARTING AT LINE NUMBER
$PUTE4: SETZ T1, ;START OFF AT 0
LDB T3,DIBUF+.BFPTR ;GET BACK 1ST DIGIT OF LINE NUMBER
REPEAT 4,<
IMULI T1,^D10
ADDI T1,-"0"(T3)
JSP T4,GETC
ERROR <EOF IN MIDDLE OF LINE SEQUENCE NUMBER>
>
IMULI T1,^D10
ADDI T1,-"0"(T3)
MOVEM T1,LINNUM ;SAVE LINE #
JRST $PUTE0 ;DO ANOTHER
;HERE WHEN WE ARE FINISHED XFER'ING AN ASCII MODE 20F OUTPUT FILE
PTAEOF: PUSHJ P,ZERFIL ;GO FILL REMAINDER OF BLOCK WITH 0S
MOVEI T1,BLKBFR ;POINT T1 AT OUTPUT BUFFER
PUSHJ P,OUT20F ;PUT OUT LAST PARTIAL BUFFER
STOR. LINSIZ,RSIZ,FHBFOO ;INSERT THE MAX LINE SIZE
PTIEOF: SKIPLE T1,RSXCTR ;SKIP IF WE EXACTLY FILLED LAST BLOCK
JRST PTXEOF ;NO, SO GO AHEAD
AOSA BLKCNT ;IF EXACT FILL,BUMP EOF TO NEXT BLOCK
;AND SET FFBYTE=0
PTXEOF: MOVEI T1,1000 ;SIZE OF A BLOCK
SUB T1,RSXCTR ;GET EOF BYTE
STOR. T1,FFBY,FHBFOO ;STORE NUMBER BYTES
MOVE T1,BLKCNT ;GET BLOCK COUNT
STOR. T1,EFBL,FHBFOO ;STORE LOW ORDER EOF BLOCK #
LSH T1,-^D16 ;DROP LOW ORDER PART OF EOF BLOCK
STOR. T1,EFBH,FHBFOO ;STORE HIGH ORDER EOF BLOCK #
;HERE WHEN WE ARE FINISHED XFER'ING TO A 20F OUTPUT FILE
PUTEOF: MOVE T1,STOCNT ;GET NUMBER OF BLOCKS IN THIS POINTER
MOVE T2,STOLBN ;GET BASE LBN FOR THIS POINTER
MOVEI T3,TMPBUF ;WHICH BUFFER TO STORETIZE
SKIPE T1 ;SKIP IF GROUP WAS LEFT UNUSED
PUSHJ P,STORET ;STORE FINAL RETRIEVAL POINTER PAIR
MOVE T1,[S$CONT] ;/CONTIGUOUS OUTPUT?
LOAD. T2,UCHA,FHBFOO ;GET OLD CHARACTERISTICS
TDNE T1,.FXSWT+TMPFDB ;CHECK
TDO T2,[UC.CON] ;TURN ON CONTIGUOUS BIT
STOR. T2,UCHA,FHBFOO ;STORE NEW CAHRACTERISTICS
MOVEI T1,TMPBUF ;POINT AT THE FHB WE BUILT
PUSHJ P,WRUFHB ;WRITE OUT FHB AS IS
MOVEI T1,TMPBUF
PUSHJ P,TYPFHU
TYPE <=>
MOVEI FP,TMPFDB
PUSHJ P,TYPFIO
MOVE T1,.FXSWT(FP)
TDNE T1,[S$ASCI]
TYPE </ASCII>
TDNN T1,[S$ASCI]
TYPE </IMAGE>
MOVE T1,.FXSWT+TMPFDB
TDNE T1,[S$CONT]
TYPE </CONTIG>
RELEAS FIO, ;RELEASE INPUT FILE
PUSHJ P,WRTSBM ;WRITE OUT STORAGE BIT MAP
PUSHJ P,WRTIBM ;WRITE OUT INDEX BIT MAP
PUSHJ P,UPDDIR ;WRITE OUT DIRECTORY BLOCK
ERROR <PUTEOF cannot update directory>
;NOW GET RID OF OLD FILE'S STORAGE, IF ANY
AOS (P) ;FORCE SKIP RETURN
TDNN F,[X%SUPER] ;SKIP IF OLD FILE EXISTED
JRST [PUSHJ P,CRLF
OUTPUT TTY,
POPJ P,]
SOS (P) ;FORGET SKIP AFTER ALL
MOVEI T1,DELBUF ;FILE TO GET RID OF
PUSHJ P,RETFHB ;RETURN STORAGE, ETC
PUSHJ P,WRTSBM ;REWRITE SBM
;IBM WILL BE THE SAME, SO WILL DIR
TDZ F,[X%SUPER] ;NOW TURN OFF SUPERCEED
TYPE </SUPERCEED
>
OUTPUT TTY,
JRST CPOPJ1 ;GIVE SKIP RETURN
;ROUTINE TO PUT 1 BYTE IN 20F OUTPUT FILE
PUT20F: SOSGE RSXCTR ;CHECK FOR ROOM IN OUTPUT
JRST PUT21F ;NO ROOM, MAKE ANOTHER BUFFER
MOVS T1,RSXPTR ;GET PDP11 BYTE POINTER INTO BUFFER
JSR PUTBYT ;INSERT BYTE
AOS RSXPTR ;INCREMENT BYTE POINTER
JRST (T4) ;RETURN
PUT21F: MOVEI T1,BLKBFR ;POINT AT OUTPUT BLOCK
PUSHJ P,OUT20F ;OUTPUT THE BLOCK
MOVEI T1,1000 ;GET NEW BYTE COUNT
MOVEM T1,RSXCTR ;INIT THE NEW COUNT
MOVSI T1,BLKBFR ;GET NEW BYTE POINTER
MOVEM T1,RSXPTR ;INIT NEW BYTE POINTER
JRST PUT20F ;TRY AGAIN
;ROUTINE TO FILL REMAINDER OF DISK BUFFER WITH 0S
ZERFIL: PUSHJ P,SAVE1 ;SAVE P1
SKIPG P1,RSXCTR ;COPY # OF BYTES REMAINING
POPJ P, ;RETURN
SETZ T3, ;THE CHARACTER TO DO
MOVS T1,RSXPTR
ZERFI1: JSR PUTBYT ;INSERT A ZERO BYTE
SOJG P1,ZERFI1 ;FINISH
POPJ P,
;ROUTINE TO GET ONE BYTE FROM THE PDP10 INPUT FILE
GETC: SOSGE DIBUF+.BFCTR ;SKIP IF BYTES REMAIN IN BUFFER
JRST GETC2 ;BRANCH IF CURRENT BUFFER EMPTY
ILDB T3,DIBUF+.BFPTR ;GET A BYTE FROM BUFFER
JRST 1(T4) ;GIVE GOOD RETURN
GETC2: IN FIO, ;TRY TO GET ANOTHER INPUT BUFFER
JRST GETC ;BRANCH TO TRY TO GET BYTE AGAIN
STATO FIO,IO.EOF ;SKIP IF END OF FILE FOR INPUT
ERROR <I/O error reading input file>
JRST (T4) ;GIVE NON SKIP IF EOF ON INPUT
;ROUTINE TO GET ONE BYTE FROM 20F INPUT FILE
RDBYTE: PUSHJ P,SAVE4
DMOVE P1,T1 ;SAVE T ACS
DMOVE P3,T3 ;SAVE T ACS
RDBYT0: SOSGE RSXCTR ;CHECK FOR MORE BYTES IN THIS BLOCK
JRST RDBYT1 ;NO, GET ANOTHER BLOCK (IF POSSIBLE)
MOVS T1,RSXPTR ;GET PDP11 BYTE POINTER
JSR GETBYT ;GET BYTE FROM BUFFER
AOS RSXPTR ;INCREMENT PDP11 BYTE POINTER
DMOVE T1,P1 ;RESTORE T ACS
MOVE T4,P4 ;RESTORE T ACS
JRST CPOPJ1 ;GIVE GOOD RETURN
RDBYT1: MOVEI T1,FHBBUF ;POINT AT THE INPUT FILE FHB
AOS T2,RSXVBN ;GET VBN #
PUSHJ P,SCNRET ;CONVERT VBN TO LBN
JRST [DMOVE T1,P1 ;RESTORE T ACS
DMOVE T3,P3 ;RESTORE T ACS
POPJ P,] ;GIVE EOF RTURN
PUSHJ P,SUSET ;POSITION TO READ THAT LBN
IN VIO,[IOWD 200,TMPBUF
0] ;READ THAT BLOCK
SKIPA
PUSHJ P,G$IER ;REPORT ERROR AND FIX STATUS
MOVEI T1,FHBBUF
MOVE T2,RSXVBN
PUSHJ P,EOFBYT
MOVEM T1,RSXCTR ;INIT THE BYTE COUNT
MOVNS T1 ;GET -VE
ADDI T1,1000 ;GET FFBYTE
MOVEM T1,FFBYTE
MOVEI T1,TMPBUF ;PDP11 BYTE POINTER
MOVSM T1,RSXPTR ;SAVE IT
JRST RDBYT0 ;GO GET A BYTE
;ROUTINE TO GET ONE PDP11 WORD FROM 20F INPUT FILE
DVWORD: PUSHJ P,SAVE2 ;SAVE SOME ACS
PUSHJ P,RDBYTE ;GET LOW ORDER BYTE
POPJ P, ;PASS ALONG ERROR RETURN
MOVE P1,T3 ;SAVE LOW BYTE
PUSHJ P,RDBYTE ;GET HIGH ORDER BYT
ERROR <NO WORD AVAILABLE FOR INPUT>
LSH T3,^D8 ;PUT HIGH ORDER BYTE IN HIGH POSITION
OR T3,P1 ;MERGE HIGH+LOW
JRST CPOPJ1 ;GIVE GOOD RETURN
; ROUTINE TO COMPUTE THE # OF BYTES IN THE REQUESTED BLOCK #
;ENTER: T1/ FHB ADR T2/ BLOCK # (BASED ON 0)
EOFBYT: PUSHJ P,SAVE4 ;SAVE SOME ACS
DMOVE P1,T1 ;SAVE INPUTS
PUSHJ P,SCNRET ;TRY TO USETI TO THAT BLOCK
JRST [SETZ T1, ;ILLEGAL, SO RETURN 0
POPJ P,] ;...
SUBI P1,FHBBUF ;COMPUTE PDP10 OFFSET
IMULI P1,4 ;THEN COMPUTE PDP11 OFFSET
MOVEI T1,1000 ;DEFAULT TO FULL BLOCK OF BYTES
LOAD. T3,EFBL,P1 ;GET LOW EOF BLOCK #
LOAD. T4,EFBH,P1 ;GET HIGH EOF BLOCK #
LSH T4,^D16
OR T3,T4
JUMPE T3,CPOPJ ;IF EOF NOT SET, GIVE A FULL BLOCK
ADDI P2,1
MOVEI T1,0
CAMLE P2,T3
POPJ P, ;NONE IF BEYOND EOF!
MOVEI T1,1000
CAME P2,T3
POPJ P,0
LOAD. T1,FFBY,P1 ;GET FIRST FREE BYTE #(EXACTLY=COUNT)
POPJ P, ;RETURN
; ROUTINE TO TYPE OUT LITERALLY THE FDB FILE SPEC
TYPFDB: PUSHJ P,SAVE1
SKIPE T1,.FXDEV(FP) ;GET VOLUME/DEVICE NAME
PUSHJ P,SIXOUT ;TYPE THE DEVIEC NAME
SKIPE .FXDEV(FP)
TYPE <:> ;TYPE SEPERATOR
SKIPE T1,.FXNAM(FP) ;GET FILE NAME
PUSHJ P,SIXOUT
SKIPE T1,.F2NAM(FP) ;GET 2ND PART OF FILE NAME
PUSHJ P,SIXOUT ;TYPE IT TOO
HLLZ T1,.FXEXT(FP) ;GET EXTENTION
JUMPN T1,[TYPE <.>
PUSHJ P,SIXOUT
JRST .+1]
SKIPN .FXDIR(FP) ;SKIP IF EXPLICIT DIRECTORY GIVEN
POPJ P, ;EXIT EARLY IF NO DIRECTORY
MOVSI T1,-6 ;GET # OF DIRECTORY PAIRS
MOVEI T2,.FXDIR(FP) ;POINT AT THEM
TYPFD1: MOVE T3,(T2) ;GET A DIRECTORY
MOVEM T3,PTHBLK+.PTPPN(T1) ;STORE IT
ADDI T2,2 ;STEP TO NEXT PAIR
AOBJN T1,TYPFD1 ;LOOP
PUSHJ P,TYPPTH
POPJ P,
; ROUTINE TO TYPE OUT THE FILE SPEC ASSOCIATED WITH CHANNEL "FIO"
TYPFIO: PUSHJ P,SAVE2 ;SAVE SOME ACS
SETZM PTHBLK ;INITIALIZE THE PTHBLK TO ZEROS
MOVE T1,[PTHBLK,,PTHBLK+1] ;...SETUP BLT POINTER
BLT T1,PTHBLK+PTHLEN-1 ;...AND INSERT THE ZEROS
MOVEI T2,FIO ;GET CHANNEL NUMBER
DEVNAM T2, ;GET DEVICE OPEN'ED ON THAT CHANNEL
MOVSI T2,'NUL' ;DEFAULT IN CASE IT FAILS
MOVEI T1,FIO ;GET CHANNEL NUMBER
MOVEM T1,PTHBLK+.PTFCN ;STORE FUNCTION CODE
MOVE T1,[XWD PTHLEN,PTHBLK] ;ARG POINTER FOR PATH. UUO
PATH. T1, ;RETURN PATH INFO FOR THAT CHANNEL
MOVEM T2,PTHBLK+0 ;INSERT DEVICE IF IT FAILS
MOVE T1,PTHBLK ;GET DEVICE NAME
PUSHJ P,SIXOUT ;TYPE THE DEVICE NAME
TYPE <:> ;GIVE SEPERATOR
; MOVE T1,.FXNAM(FP) ;GET OUTPUT FILE NAME
MOVE T1,LERBLK+.RBNAM ;GET FILE NAME
PUSHJ P,SIXOUT ;TYPE OUTPUT FILE NAME
TYPE <.> ;GIVE SEPERATOR
HLLZ T1,LERBLK+.RBEXT ;GET FILE EXTENSION FROM RIB
PUSHJ P,SIXOUT ;TYPE OUTPUT FILE TYPE
;ROUTINE TO TYPE THE PATH SPEC IN THE PTHBLK
TYPPTH: TYPE <[> ;START PATH OFF WITH [
HLRZ T1,PTHBLK+2 ;GET THE P, PART OF P,PN
PUSHJ P,OCTOUT ;TYPE P, PART
TYPE <,> ;GIVE SEPERATOR
HRRZ T1,PTHBLK+2 ;GET THE ,PN PART
PUSHJ P,OCTOUT ;TYPE THE ,PN PART
MOVEI P1,PTHBLK+3 ;POINT AT NEXT SFD
TYPPT1: SKIPN T1,(P1) ;PICK UP NEXT SFD NAME
JRST TYPPT2 ;DONE
TYPE <,> ;GIVE SEPERATOR
MOVE T1,(P1) ;PICK UP SFD NAME
PUSHJ P,SIXOUT ;TYPE SFD NAME
AOJA P1,TYPPT1 ;LOOP FOR ALL SFD NAMS
TYPPT2: TYPE <]> ;END PATH WITH ]
POPJ P,0 ;RETURN
;ROUTINE TO TYPE OUT A L/E/R ERROR GIVEN THE L/E/R BLOCK
LSTLER: TYPE <? LOOKUP/ENTER/RENAME code >
HRRZ T1,LERBLK+.RBEXT ;GET THE ERROR CODE
PUSHJ P,OCTOUT ;TYPE ERROR CODE IN OCTAL
TYPE < for >
MOVE T1,LERBLK+.RBNAM ;GET FILE NAME FROM LER BLOCK
PUSHJ P,SIXOUT ;TYPE FILE NAME
TYPE <.> ;TYPE SEPERATOR
HLLZ T1,LERBLK+.RBEXT ;GET FILE NAME EXTENSION
PUSHJ P,SIXOUT ;TYPE FILE NAME EXTENSION
MOVE T1,LERBLK+.RBPPN ;GET PPN OF FILE
JUMPE T1,LSTDSH ;BRANCH IF USER SPECIFIED DEFAULT PATH
TLNN T1,-1 ;SKIP IF USER SPECIFIED EXPLICIT PPN
JRST LSTPTH ;GO LIST PATH FROM BLOCK
PUSH P,T1 ;SAVE T1
HLRZS T1 ;GET LEFT HALF OF PPN
TYPE <[> ;TYPE [ TO START PPN
PUSHJ P,OCTOUT ;TYPE LEFT HALF OF PPN
TYPE <,> ;TYPE PPN SEPERATOR
HRRZ T1,(P) ;RECOVER RIGHT HALF OF PPN
PUSHJ P,OCTOUT ;TYPE RIGHT HALF
TYPE <]> ;END PPN WITH ]
POP P,(P) ;WASTE COPY OF PPN
PUSHJ P,CRLF ;END WITH CRLF
JRST .ERR ;RESUME ERROR PROCESSING
LSTDSH: TYPE <[-]>
PUSHJ P,CRLF
JRST .ERR
LSTPTH: TYPE <[path]>
PUSHJ P,CRLF
JRST .ERR
SUBTTL COMMANDS -- UFD
C$UFD: PUSHJ P,TTYPHY
PUSHJ P,FILIN ;MUST GET SOME SPEX
SKIPN FP,IPLIST ;MUST BE A LIST
PUSHJ P,ILLCMD
MOVE T1,[FX.EQL] ;DID WE SEEN AN EQUAL?
SETO T3, ;T3=-1=COMPLETELY SPECIFIED
C$UFD0: SKIPE .FXNAM(FP) ;
ERROR <Volume labels not supported>
TDNN T1,.FXMOD(FP) ;
SKIPE .FXEXT(FP) ;
PUSHJ P,ILLCMD
CAMN T3,.FXDNM(FP) ;SKIP IF DIRECTORY NAME WILD
CAME T3,.F2DNM(FP) ;SKIP IF DIRECTORY NAME IS NOT WILD
PUSHJ P,ILLCMD ;COMPLAIN IF DIRECTORY NAME WILD
SKIPE .FXDIR+2(FP) ;SKIP IF NO SFD LIST
PUSHJ P,ILLCMD ;COMPLAIN IF SFD LST GIVEN
HRRZ FP,.FXLNK(FP) ;STEP TO NEXT SPEC IF ANY
JUMPN FP,C$UFD0 ;CHECK ANOTHER SPEC IF PRESENT
HRRZ FP,IPLIST ;POINT AT FIRST SPEC
C$UFD1: PUSHJ P,C$UFDA ;GO PROCESS ONE OF THEM
HRRZ FP,.FXLNK(FP) ;STEP TO NEXT FILE SPEC, IF ANY
JUMPN FP,C$UFD1 ;BRANCH IF MORE TO PROCESS
POPJ P, ;DONE
C$UFDA: PUSHJ P,SAVFF ;SAVE THE FIRST FREE CORE POINTER
PUSHJ P,SAVFP ;SAVE THE FILE POINTER
PUSHJ P,OPNVOL ;OPEN THE VOLUME FOR FILE I/O
; LOOK FOR AN ALREADY EXISTING DIRECTORY FILE FOR THE SAME UIC
; IF IT IS PRESENT, ABORT WITH AN ERROR
DMOVE T1,.FXDIN(FP) ;GET DIRECTORY NAME
MOVEM T1,.FXNAM+UFDFDB ;SAVE 1ST PART
MOVEM T2,.F2NAM+UFDFDB ;SAVE 2ND PART TOO
SETOM UFDFDB+.FXNMM ;MAKE NAME NOT APPEAR WILD
SETOM UFDFDB+.F2NMM ;MAKE SURE 2ND 6 LETTERS APPEAR NOT WILD
HRRZI T1,'DIR' ;PICK UP FILE TYPE FOR DIRECTORY FILE
HRLOM T1,UFDFDB+.FXEXT ;SPECIFY FILE TYPE AND ENSURE NOT WILD
SETZM UFDFDB+.FXDIR ;SPECIFY EXPLICIT OWNER UIC OF [0,0]
SETOM UFDFDB+.FXDIM ;MAKE SURE UIC FIELD IS NOT WILD
SETZM UFDFDB+.FXDIR+2 ;MAKE SURE UIC FIELD HAS NO SFD!
MOVE T1,['000000']
MOVEM T1,UFDFDB+.FXDIN ;DIRECTORY NAME
SETZM UFDFDB+.F2DIN
SETOM UFDFDB+.FXDNM
SETOM UFDFDB+.F2DNM
PUSHJ P,RLDINI ;INITIALIZE THE 20F .LKWLD ROUTINE
MOVEI T1,UFDFDB ;POINT AT FDB TO FIND
MOVEI T2,FAKFDB ;POINT AT FDB TO EXPAND INTO
PUSHJ P,NXTFDB ;SCAN FOR ANY MATCHING FILES
SKIPA ;SKIP OUT IF NONE FOUND (GOOD!)
ERROR <Directory already exists>
; SCAN THE OWNING DIRECTORY (IE: [0,0]) FOR A HOLE WE CAN USE
SETZ P1, ;0S
EXCH P1,UFDFDB+.FXNAM ;REMEMBER FILE NAME IN SIXBIT
MOVE P4,UFDFDB+.F2NAM ;REMEMBER 2ND HALF AS WELL
SETZM UFDFDB+.FXDEV ;ENSURE ALL ZEROS
HRRZS UFDFDB+.FXEXT ;EXPLICIT EXT OF 0S
C$UFD2: PUSHJ P,RLDINI ;INITIALIZE THE 20F FILE FINDER
MOVEI T1,UFDFDB ;FDB TO FIND
MOVEI T2,FAKFDB ;FDB TO WRITE INTO
PUSHJ P,NXTFDB ;SEARCH FOR THE ENTRY
JRST C$UFD3 ;DARN, AREN'T ANY. EXTEND AND TRY AGAIN
; ALLOCATE AN FHB, FILL IT IN AND WRITE IT OUT.
MOVEI P2,<UFDFHB-FHBBUF>*4 ;GET OFFSET
MOVE P3,WDIOFF
SUBI P3,.DIROFF
SETZ T1, ;NO SPECIAL FILENUMBER
PUSHJ P,ALCFHB ;GO ALLOCATE AN FHB #
;? MOVEM T1,UFDFHB ;SAVE IT
MOVEI T2,UFDFHB
PUSHJ P,INIFHB ;GO MAKE UP AN FHB FOR ME
HLRZ T1,P1 ;GET 1ST PART OF NAME
PUSHJ P,C6T5 ;CONVERT TO RAD50
STOR. T1,FNM1,P2 ;STORE INTO OUR FHB
STOR. T1,UFN1,P3 ;STORE 1ST PART IN DIRECTORY TOO
HRRZ T1,P1 ;GET 2ND PART OF NAME
PUSHJ P,C6T5 ;CONVERT TO RAD50
STOR. T1,FNM2,P2 ;STORE INTO OUR FHB
STOR. T1,UFN2,P3 ;STORE 2ND PART IN DIRECTORY TOO
HLRZ T1,P4 ;GET 3RD PART OF NAME
PUSHJ P,C6T5 ;CONVERT TO RAD50
STOR. T1,FNM3,P2 ;STORE INTO OUR FHB
STOR. T1,UFN3,P3 ;STORE INTO DIRECTORY FILE TOO
MOV. [.RAD50 <DIR>],FTYP,P2 ;STORE FILE TYPE INTO OUR FHB
MOV. [.RAD50 <DIR>],UFTY,P3 ;STORE FILE TYPE IN DIRECTORY TOO
LOAD. T1,FSEQ,P2 ;GET SEQ# IN FHB
STOR. T1,UFSQ,P3 ;AND COPY SEQ# TO DIRECTORY
STOR. [UC.CON],UCHA,P2 ;SPECIFY CONTIGUOUS FILE
STOR. [1],RTYP,P2 ;FILE TYPE=#1, FIXED LENGTH RECORDS
STOR. [20],RSIZ,P2 ;RECORD SIZE=16. BYTES (8 WORDS)
SKIPN T1,V$ALLOC(FP) ;GET /ALLOC:n VALUE
MOVEI T1,^D1000 ;MAKE ROOM FOR AT LEAST 1000 FILES
IDIVI T1,^D32 ;COMPUTE NUMBER OF BLOCKS REQUIRED
CAIE T2,0 ;EXACT FIT?
ADDI T1,1 ;NO, ADD ONE MORE BLOCK
MOVEM T1,V$SIZE(FP)
LDB T2,[POINT 16,T1,19] ;GET HI WORD
STOR. T2,HIBH,P2 ;STORE HIGH PART OF HIGH BLOCK
STOR. T1,HIBL,P2 ;STORE LOW PART OF HIGH BLOCK
AOS T1 ;UP BY ONE TO GET EOF BLOK#
LDB T2,[POINT 16,T1,19] ;GET HI WORD
STOR. T2,EFBH,P2 ;...
STOR. T1,EFBL,P2 ;...SO BLOCK HAVING EOF IS #2
SKIPE V$FPRO(FP) ;?
STOR. V$FPRO(FP),FPRO ;USE HIS PROTECTION IF REQUESTED
SKIPN T1,V$SIZE(FP)
MOVEI T1,1
MOVEM T1,V$SIZE(FP)
PUSHJ P,SCNSBM ;GO FIND 1 BLOCK
ERROR <Cannot allocate space to the UFD file>
CAMLE T1,V$SIZE(FP) ;BACK UP?
MOVE T1,V$SIZE(FP) ;YES, PLEASE
MOVEM T1,V$SIZE(FP) ;SAVE SIZE WE ACTUALLY GOT
IMULI T1,^D32 ;COMPUTE # OF ENTRIES
MOVEM T1,V$ALLO(FP) ;SAVE # OF ENTRIES
MOVE P1,T2 ;SAVE THE BLOCK #
MOVEI T3,UFDFHB ;POINT AT FHB TO STORETIZE
MOVE T1,V$SIZE(FP) ;GET # OF BLOCKS TO GET
PUSHJ P,STORET ;STORE RETRIEVAL PAIR, FIXUP SBM
MOVEI T1,UFDFHB ;POINT AT FHB
PUSHJ P,WRUFHB ;WRITE A USER FHB
MOVE T1,P1 ;GET BLOCK # ALLOCATED
MOVE T2,V$SIZE(FP) ;GET NUMBER OF BLOCKS ALLOCATED
PUSHJ P,SUSET ;POSITION TO IT
C$UFD4: OUT VIO,[IOWD 1,LOWZRO ;
0] ;GO ZERO IT
SKIPA
TYPE <% Cannot initialize directory to zeroes
>
SOJG T2,C$UFD4 ;LOOP ZEROING IT ALL
PUSHJ P,WRTIBM ;WRITE INDEX BIT MAP
PUSHJ P,WRTSBM ;WRITE STORAGE BIT MAP
LOAD. T1,FNUM,P2 ;GET ALLOCATED FILE NUMBER
STOR. T1,UFNO,P3 ;STORE IN DIRECTORY ENTRY
STOR. [0],UFRV,P3 ;STORE 0 IN THE MAGIC PLACE
STOR. [1],UVER,P3 ;STORE GENERATION # IN DIRECTORY
MOVE T1,WDIPBN ;GET PHYSICAL BLOCK #
PUSHJ P,SUSET ;POSITION TO DIRECTORY BLOCK
OUT VIO,[IOWD 200,WDIBUF ;REWRITE THE MODIFIED DIRECTORY BLOCK
0] ;
SKIPA
TYPE <% Failed to insert new ufd name in owning directory
>
TDON F,[X%INTRO]
TYPE <Directories created:
>
MOVEI T1,UFDFHB
PUSHJ P,TYPFHU
LOAD. T1,FPRO,P2
PUSHJ P,P11OUT
TYPE </ALLOCATE:>
MOVE T1,V$ALLO(FP)
PUSHJ P,DECOUT
PUSHJ P,CRLF
POPJ P, ;ALL DONE
;HERE TO EXPAND THE 000000.DIR TO MAKE ROOM FOR NEW UFD
C$UFD3: MOVEI T1,BUF444 ;POINT AT MFD
PUSHJ P,EXPDIR ;TRY
ERROR <Cannot expand size of [0,0].DIR>
JRST C$UFD2 ;GO RESCAN
SUBTTL COMMANDS -- DESTROY
C$DEST: PUSHJ P,TTYPHY ;FORCE OUTPUT TO PHYSICAL TTY
PUSHJ P,FILIN ;GET LIST OF VOLUMES
SKIPN FP,IPLIST ;SKIP IF A LIST GIVEN
PUSHJ P,ILLCMD ;COMPLAIN IF NO VOLUMES TO DESTROY
C$DES0: PUSHJ P,D$RSX ;DESTROY AN RSX FILE SYSTEM
HRRZ FP,.FXLNK(FP) ;FETCH LINK TO NEXT VOLUME, IF ANY
JUMPN FP,C$DES0 ;BRANCH IF ANOTHER VOLUME TO DESTROY
POPJ P,0 ;RETURN IF ALL VOLUMES DESTROYED
; ROUTINE TO DESTROY THE FRONT END AREA OF RSX
D$RSX: PUSHJ P,OPNVIO ;OPEN VOLUME FOR I/O
SKIPE FAKVOL ;SKIP IF REAL VOLUME NAME GIVEN
ERROR <Can't DESTROY logical volume>
TYPE <Do you really want to DESTROY >
PUSHJ P,VOLOUT ;TYPE VOLUME NAME
PUSHJ P,YESNO
POPJ P, ;NO
PUSHJ P,F11ZAP ;FIND AND ZAP F11 HOME BLOCK
DMOVE T1,[SIXBIT .FE.
SIXBIT .SYS.] ;LOAD FILENAME, EXTENSION FOR LOOKUP
DMOVE T3,[0
1,,4] ;LOAD PPN FOR LOOKUP
LOOKUP VIO,T1 ;FIND FE.SYS
TYPE <% FE.SYS not found>,D$RSX0
SETZM BLKBFR+.RBNAM ;GET RID OF FILE NAME
USETI VIO,0 ;SET TO READ RIB
INPUT VIO,[IOWD 200,BLKBFR ;
0] ;READ RIB OF FE.SYS
CAME T1,BLKBFR+.RBNAM ;SIMPLISTIC CHECK
ERROR <Cannot acquire rib for FE.SYS>
; **** N.B. **** THIS MIGHT NOT WORK TOO WELL ON A MULTI UNIT STRUCTURE
MOVE T1,BLKBFR+.RBSLF ;GET BLOCK # OF THE RIB
PUSHJ P,SUSET ;POSITION TO IT
MOVE T1,[RP.NDL] ;GET THE NO DELETE BIT
ANDCAM T1,.RBSTS+BLKBFR ;TURN IT OFF
OUTPUT VIO,[IOWD 200,BLKBFR
0] ;ULP - REWRITE RIB
CLOSE VIO,CL.DAT ;DELETE THE ACCESS TABLE
DMOVE T1,[SIXBIT .FE.
SIXBIT .SYS.] ;RELOAD THE FILE NAME FOR THE LOOKUP
DMOVE T3,[0
1,,4] ;RELOAD THE PPN FOR THE LOOKUP
LOOKUP VIO,T1 ;LOOKUP THE FILE AGAIN
ERROR <FE.SYS disappeared>
SETZB T1,T2 ;ZERO THE FILE NAME FOR DELETE UUO
SETZB T3,T4 ;MAKE WHOLE BLOCK ZEROS
RENAME VIO,T1 ;DELETE FE.SYS
ERROR <Cannot delete FE.SYS>
TYPE <[>
MOVE T1,FEUNIT
PUSHJ P,SIXOUT
TYPE <:FE.SYS[1,4] deleted, >
MOVE T1,BLKBFR+.RBALC ;GET SIZE OF FILE
PUSHJ P,DECOUT ;TYPE SIZE OF FILE IN BLOCKS
TYPE < blocks freed]>
D$RSX0: PUSHJ P,CRLF
PUSHJ P,G10HOM ;READ HOME BLOCKS
SETZM HOME1+HOMFE0 ;BREAK LINK IN HOME BLOCK TO FE.SYS
SETZM HOME1+HOMFE1 ;BREAK LENGTH IN HOME BLOCK
SETZM HOME2+HOMFE0 ;BREAK DATA IN 2ND HOME BLOCK TOO...
SETZM HOME2+HOMFE1 ;...
PUSHJ P,ZERHOM ;
RELEASE VIO, ;RELEASE THE VOLUME
POPJ P,0 ;RETURN
; ROUTINE TO FIND AND ZAP THE FILES-11 HOME BLOCK FOR THIS VOLUME
; TO LESSEN THE POSSIBILITY THAT RSX20F WILL STUMBLE ACROSS THIS
; NOW OBSOLETE HOME BLOCK IN A SEARCH FOR A HOME BLOCK LATER.
F11ZAP: PUSHJ P,G11HOM ;FIGURE OUT WHERE IT IS
POPJ P, ;OH WELL, CAN'T FIND IT
MOVE T1,H11LBN ;GET THE HOME BLOCK BLOCK#
PUSHJ P,SUSET ;POSITION TO THE BLOCK
OUTPUT VIO,[IOWD 1,LOWZRO ;ZERO IT
0] ;
POPJ P, ;RETURN WITH F11 HOME BLOCK DESTROYED
SUBTTL COMMANDS -- ZERO
; ZERO {unit name}{/SIZE:<# OF BLOCKS>}
C$INI: PUSHJ P,TTYPHY ;...OPEN UP THE TTY OUTPUT CHANNEL
PUSHJ P,FILIN ;GET UNIT, SWITCHES, ETC
SKIPN FP,IPLIST ;SKIP IF ANYTHING TO DO
PUSHJ P,ILLCMD
C$ZER0: PUSHJ P,Z$RSX ;GO ZERO IT
HRRZ FP,.FXLNK(FP) ;STEP TO NEXT FILE SPEC
JUMPN FP,C$ZER0 ;LOOP IF ANOTHER LEFT
POPJ P, ;RETURN WHEN ALL DONE
; HERE TO ZERO RSX20F FILE SYSTEM
Z$RSX: PUSHJ P,DOGETS ;GO DO GETTABS AS NEEDED
PUSHJ P,OPNVIO ;OPEN UP FOR VOLUME I/O
PUSHJ P,MKFESY ;MAKE THE FE.SYS FILE
PUSHJ P,ZAPHOM ;GET RID OF OBSOLETE HOME BLOCKS
PUSHJ P,MAK11H ;MAKE THE FILES11 HOME BLOCK
PUSHJ P,MAKSBM ;MAKE THE STORAGE BIT MAPS
PUSHJ P,MAKIBM ;MAKE THE INDEX BIT MAP
PUSHJ P,WRT111 ;GO WRITE (1,1,0) INDEXF.SYS
PUSHJ P,WRT222 ;GO WRITE (2,2,0) BITMAP.SYS
PUSHJ P,WRT333 ;GO WRITE (3,3,0) BADBLK.SYS
PUSHJ P,WRT444 ;GO WRITE (4,4,0) 000000.DIR;1
PUSHJ P,WRT555 ;GO WRITE (5,5,0) CORIMG.SYS;1
PUSHJ P,MAKLOS ;GO MAKE TOPS10.SYS;1,2,3,4,5 files
PUSHJ P,WRTMFD ;WRITE OUT THE MFD DATA
PUSHJ P,WRTSBM ;WRITE THE STORAGE BIT MAPS
PUSHJ P,WRTIBM ;WRITE THE INDEX BIT MAP
PJRST WRTHOM ;WRITE TOPS-10 HOME BLOCKS
; SUBROUTINE TO "CREATE" THE INDEXF.SYS (1,1,0) FILE
WRT111: MOVEI T1,1 ;REQUEST FILE #1
MOVEI T2,FHBBUF ;WHICH ONE TO INITIALIZE
PUSHJ P,INIFHB ;INITIALIZE THE FILE HEADER BLOCK
MOV. [.RAD50 <INDEXF>],FNAM ;STORE FILE NAME
MOV. [.RAD50 <SYS>],FTYP ;STORE FILE TYPE
; ATTACH THE BOOT BLOCK TO THIS FILE
MOVE T1,[1] ;1 BLOCK
MOVE T2,[0] ;AT BLOCK 0
MOVEI T3,FHBBUF ;POINT AT FHB TO STORETIZE
PUSHJ P,STORET ;...STORE RETRIEVAL POINTERS
; ATTACH THE FILES11 HOME BLOCK
MOVE T1,[1] ;1 BLOCK
MOVE T2,H11LBN ;AT THE HOME BLOCK
MOVEI T3,FHBBUF ;POINT AT FHB TO STORETIZE
PUSHJ P,STORET ;...STORE RETRIEVAL POINTERS
; ATTACH THE FHB SAT
LOAD. T1,FMAX ;GET # OF FILE HEADERS PERMITTED
IDIVI T1,^D4096 ;COMPUTE # OF BLOCKS NEEDED FOR FHB SAT
CAIE T2,0 ;ON THE NOSE?
ADDI T1,1 ;NO, SO ADD ONE MORE
MOVE T2,H11LBN ;GET THE HOME BLOCK ADDRESS
ADDI T2,1 ;HOME BLOCK ADR+1 IS FHB SAT ADR
MOVEM T2,IBMLBN ;BLOCK# OF FHB SAT
MOVE T3,T1 ;COPY THE # OF BLOCKS
ADD T3,T2 ;COMPUTE 1ST FHB BLOCK
MOVEM T3,FHBLBN ;REMEMBER IT
MOVEI T3,FHBBUF ;POINT AT FHB TO STORETIZE
PUSHJ P,STORET ;...STORE RETRIEVAL POINTERS
; ATTACH THE FHB LIST
MOVEI T1,M.INFH ;GET INITIAL NUMBER OF FILE HEADERS
MOVE T2,FHBLBN ;GET WHERE THEY START
MOVEI T3,FHBBUF ;POINT AT FHB TO STORETIZE
PUSHJ P,ZERRET ;ZERO THE BLOCKS FIRST
PUSHJ P,STORET ;...STORE RETRIEVAL POINTERS
; WRITE THE FHB
MOVE T1,[FHBBUF,,BUF111]
BLT T1,BUF111+177 ;COPY FHB FOR INDEXF TO WHERE WRUFHB WANTS IT
PUSHJ P,WRTFHB ;GO WRITE IT (AND FHB SATS)
POPJ P, ;ALL DONE
; SUBROUTINE TO "CREATE" THE BITMAP.SYS (2,2,0) FILE
WRT222: MOVEI T1,2 ;REQUEST FILE #2
MOVEI T2,FHBBUF ;
PUSHJ P,INIFHB ;INITIALIZE THE FILE HEADER BLOCK DATA
MOV. [.RAD50 <BITMAP>],FNAM ;STORE FILE NAME
MOV. [.RAD50 <SYS>],FTYP ;STORE FILE TYPE
; ATTACH THE BM BUFFER BLOCK TO BITMAP.SYS
MOVE T1,[1] ;1 BLOCK
MOVE T2,FFBLOK ;1ST FREE BLOCK
MOVEM T2,SBMLBN ;SAVE LBN OF IT
MOVEI T3,FHBBUF ;POINT AT FHB TO STORETIZE
PUSHJ P,STORET ;...STORE RETRIEVAL POINTER
; ATTACH THE SAT BLOCKS TO BITMAP.SYS
MOVE T1,LSTLBN ;GET LAST BLOCK # AVAILABLE TO OUR "VOLUME"
IDIVI T1,^D4096 ;COMPUTE # OF BLOCKS IN SAT FOR OUR VOLUME
CAIE T2,0 ;FIT EXACTLY?
ADDI T1,1 ;NO, SO ADD ANOTHER BLOCK
MOVE T2,FFBLOK ;1ST FREE BLOCK
MOVEI T3,FHBBUF ;POINT AT FHB TO STORETIZE
PUSHJ P,STORET ;...STORE RETRIEVAL POINTER
PUSHJ P,WRTFHB ;WRITE THE FILE HEADER OUT
POPJ P, ;RETURN
; SUBROUTINE TO WRITE OUT (3,3,0) BADBLK.SYS
WRT333: MOVEI T1,3 ;REQUEST FILE #3
MOVEI T2,FHBBUF
PUSHJ P,INIFHB ;INITIALIZE THE FILE HEADER BLOCK DATA
MOV. [.RAD50 <BADBLK>],FNAM ;STORE FILE NAME
MOV. [.RAD50 <SYS>],FTYP ;STORE FILE TYPE
;; N.B.: NO BLOCKS NEED TO BE ATTACHED!
PUSHJ P,WRTFHB ;WRITE THE FILE HEADER OUT
POPJ P, ;RETURN
; SUBROUTINE TO WRITE (4,4,0) 000000.DIR (IE: THE MFD)
WRT444: MOVEI T1,4 ;REQUEST FILE #4
MOVEI T2,FHBBUF
PUSHJ P,INIFHB ;INITIALIZE THE FHB
MOV. [.RAD50 <000000>],FNAM ;STORE THE FILE NAME
MOV. [.RAD50 <DIR>],FTYP ;STORE THE FILE TYPE
STOR. [UC.CON],UCHA ;DECLARE FILE IS CONTIGUOUS
STOR. [1],RTYP ;RECORD TYPE=#1, FIXED LENGTH RECORDS
STOR. [20],RSIZ ;RECORD SIZE=16 (BYTES, ONLY 8 WORDS)
STOR. [1],HIBL
STOR. [2],EFBL ;
MOVEI T1,1 ;1 BLOCK
MOVE T2,FFBLOK ;AT NEXT FREE PLACE
MOVEM T2,MFDLBN
MOVEI T3,FHBBUF ;POINT AT FHB TO STORETIZE
PUSHJ P,STORET ;STORE RETRIEVAL POINTERS
MOVE T1,MFDLBN ;GET THE BLOCK WE WANT TO USE
PUSHJ P,SUSET ;POSITION TO IT
OUTPUT VIO,[IOWD 1,LOWZRO
0] ;INITIALIZE IT TO ZEROES
MOVE T1,MFDLBN
PUSHJ P,TAKSBM ;TAKE IT AWAY FROM SAT
JFCL
PJRST WRTFHB
; ROUTINE TO WRITE OUT THE MFD DATA AFTER [0,0] CHANGES
WRTMFD: MOVE T1,MFDLBN ;GET BLOCK AGAIN
PUSHJ P,SUSET ;POSITION DISK
OUT VIO,[IOWD 200,MFDDAT ;WRITE OUT THE MFD DATA
0] ;...
POPJ P, ;RETURN IF I/O WAS GOOD
ERROR <Write failed trying to init MFD data>
; SUBROUTINE TO WRITE (5,5,0) CORIMG.SYS
WRT555: MOVEI T1,5 ;REQUEST FILE #5
MOVEI T2,FHBBUF
PUSHJ P,INIFHB ;INITIALIZE THE FHB
MOV. [.RAD50 <CORIMG>],FNAM
MOV. [.RAD50 <SYS>],FTYP
STOR. [UC.CON],UCHA ;DECLARE FILE IS CONTIGUOUS
MOVEI T1,^D100 ;100 BLOCKS
MOVE T2,FFBLOK ;GET THE FIRST FREE BLOCK
MOVEI T3,FHBBUF ;POINT AT FHB TO STORETIZE
PUSHJ P,STORET ;STORE RETRIEVAL POINTERS
STOR. [^D100],HIBL ;INSERT HIGHEST BLOK # ALLOCATED
STOR. [^D101],EFBL ;INSERT "FIRST FREE" BLOK (IE: EOF BLOK)
PUSHJ P,WRTFHB ;GO WRITE IT OUT
POPJ P,0
; ROUTINE TO CREATE A BUNCH OF FILES IN [0,0] THAT ARE ACTUALLY
; THE BLOCKED TIED UP TO THE TOPS-10 FILE STRUCTURE (IF ANY)
; AND WILL THUS ACCOUNT FOR THE "LOST" BLOCKS.
; (THIS IS NEEDED ONLY TO KEEP "VFY" FROM COMPLAINING.
MAKLOS: PUSHJ P,SAVE4 ;SAVE SOME ACS
MOVEI P4,6 ;START WITH FILE #6
SKIPN P3,FSTLBN ;SKIP IF LOST FILES NEEDED
POPJ P, ;EXIT IF VOLUME ISN'T EMBEDDED
MOVEI P2,1 ;CURRENT BASE LBN #
;BLOCK 0 IS ALREADY CLAIMED!
MAKLO1: MOVE T1,P3 ;T1=NUMBER OF BLOCKS
;$ CAILE T1,^D26010 ;SKIP IF IT WILL ALREADY FIT
;$ MOVEI T1,^D26010 ;REDUCE IT SO IT WILL
SUB P3,T1 ;AND ACCOUNT FOR BLOCKS USED
MOVEI T2,(P4) ;T2=FILE #
MOVE T3,P2 ;T3=BASE LBN#
ADD P2,T1 ;UPDATE BASE LBN# FOR NEXT PASS
PUSHJ P,LOSFIL ;MAKE A "LOST" FILE
ADDI P4,1 ;GO FOR NEXT FILE NUMBER
JUMPN P3,MAKLO1 ;MAKE ANOTHER IF NEEDED
POPJ P,
;ROUTINE TO MAKE A LOST FILE
;T1=# BLOCKS (DO NOT CALL WITH T1 .GT. ^D26000 (APPROX)
;T2=FILE#
;T3=BASE LBN#
LOSFIL: PUSHJ P,SAVE4 ;SAVE SOME ACS
DMOVE P1,T1 ;SAVE T1,T2
DMOVE P3,T3 ;SAVE T3,T4
MOVE T1,T2 ;GET FILE #
MOVEI T2,FHBBUF ;POINT AT FHB
PUSHJ P,INIFHB ;INITIALIZE FHB
MOV. [.RAD50 <TOPS10>],FNAM ;INITIALIZE NAME
MOV. [.RAD50 <NDL>],FTYP ;STORE UNIQUE FILE TYPE
STOR. P2,FVER ;STORE GENERATION NUMBER
STOR. P2,FSEQ ;STORE FAKE SEQUENCE # TOO
LOSFI1: MOVEI T1,^D255 ;# OF BLOCKS TO GRAB
CAMLE T1,P1 ;SKIP IF THAT IS OK
MOVE T1,P1 ;DO ALL OF REMAINDER IF LESS THAN 255
SUB P1,T1 ;ADJUST COUNT FOR NEXT PASS
MOVE T2,P3 ;GET THE BASE LBN# OF THEM
ADD P3,T1 ;ADJUST BASE LBN FOR NEXT PASS
MOVEI T3,FHBBUF ;POINT AT BUFFER
PUSHJ P,STORET ;GO ARRANGE FOR IT
JUMPN P1,LOSFI1 ;LOOP IF MORE BLOCKS TO GRAB
PUSHJ P,WRTFHB ;GO WRITE THE FILE
POPJ P,
; SUBROUTINE TO DESTROY ANY BLOCKS THAT MIGHT BE OLD HOME BLOCKS
ZAPHOM: MOVE T1,FSTLBN ;GET FIRST LBN
PUSHJ P,SUSET ;POSITION TO IT
OUTPUT VIO,[IOWD 1,LOWZRO ;
0] ;WRITE 1ST LBN TO ZEROES
AOS T1,LASSET ;PICK UP 2ND LBN
ZAPHO1: PUSHJ P,SUSET ;POSITION TO IT
OUTPUT VIO,[IOWD 1,LOWZRO ;
0] ;WRITE NEXT LBN TO ZEROES
MOVE T1,LASSET ;GET LAST I/O BLOCK
TRZ T1,377 ;TRIM OFF LOW ORDER BITS
ADDI T1,400 ;ADVANCE TO NEXT POSSIBLE HOME BLOCK
CAMGE T1,LSTLBN ;SKIP IF BEYOND BOUNDS OF VOLUME
CAMLE T1,H11LBN ;SKIP IF BELOW NEW HOME BLOCK #
POPJ P, ;ALL DONE IF BEYOND BOUNDS
JRST ZAPHO1
; SUBROUTINE TO MAKE THE FILES11 HOME BLOCK (AND WRITE IT OUT)
MAK11H: SETZM H11BUF ;
MOVE T1,[H11BUF,,H11BUF+1]
BLT T1,H11BUF+177 ;CLEAR FILES-11 HOME BLOCK ('CEPT DECFILE11A)
MOVE T1,[TMP166,,H11BUF+166]
BLT T1,H11BUF+177 ;INSERT MAGIC CONSTANTS
SKIPN T1,V$MAXF(FP) ;
MOVE T1,[M.FMAX] ;GET DEFAULT
IDIVI T1,^D4096 ;DIVIDE BY # BITS PER DISK BLOCK
CAIE T2,0 ;ANY LEFT OVER?
ADDI T1,1 ;YES, NEED ONE MORE
STOR. T1,IBSZ ;STORE "INDEX-BIT-MAP SIZE" (FILE HEADER SAT)
MOVE T1,H11LBN ;GET BLOCK# OF HOME BLOCK
ADDI T1,1 ;+1 MAKES IT BLOCK# OF INDEX BIT MAP
STOR. T1,IBLL ;STORE LOW PART OF ADDRESS OF FH SAT
LSH T1,-^D16 ;GET NEXT WORD
STOR. T1,IBLH ;STORE HIGH PART OF ADDRESS OF FH SAT
SKIPN T1,V$MAXF(FP) ;
MOVE T1,[M.FMAX]
STOR. T1,FMAX ;STORE IN HOME BLOCK
STOR. [M.SBCL],SBCL ;STORE CLUSTER SIZE
STOR. [401],VLEV ;STORE STRUCTURE LEVEL
PUSHJ P,MAKLAB ;GO INSERT THE VOLUME LABEL(S)
MOVE T1,.FXDIR(FP) ;GET OWNDER'S UIC
HLRZ T2,T1 ;GET PROJECT #
DPB T2,[POINT 8,T1,27]
SKIPN T1
MOVE T1,[M.VOWN] ;DEFAULT IT
STOR. T1,VOWN ;STORE VOLUME OWNER'S UIC
SKIPN T1,V$VPRO(FP) ;GET VOLUME PROTECTION
MOVE T1,[M.VPRO] ;NONE, GET DEFAULT
STOR. T1,VPRO ;PUT INTO HOME BLOCK
MOVE T1,[M.VCHA] ;GET DEFAULT VOLUME CHARACTERISTICS
TDZ T1,V$CHAR(FP) ;TURN OFF APPROPRIATE BITS
STOR. T1,VCHA ;STORE VOLUME CHARACTERISTICS
SKIPN T1,V$FPRO(FP) ;ANYTHING?
LDB T1,[POINTR(.FXMOD(FP),FX.PRO)]
SKIPN T1
MOVE T1,[M.DFPR] ;FINAL DEFAULT
STOR. T1,DFPR ;STORE DEFAULT FILE PROTECTION
STOR. [M.WISZ],WISZ ;STORE # OF RET POINTERS IN WINDOW
SKIPN T1,V$EXTE(FP) ;GET IT IF SPECIFIED
MOVE T1,[M.FIEX] ;ELSE DEFAULT IT
STOR. T1,FIEX ;STORE DEFAULT #BLKS IN AN EXTEND OPERATION
STOR. [M.LRUC],LRUC ;STORE #ENTRIES IN DIRECTORY LRU
MOVE T1,LOCDAY ;GET TODAY
PUSHJ P,MAKSD ;MAKE 2 DIGITS ASCII
MOV. T1,VDAY ;STORE IT
MOVE T1,LOCMON ;GET MONTH
MOV. MONTAB-1(T1),VMON;STORE MONTH
MOVE T1,LOCYER ;GET YEAR
SUBI T1,^D1900 ;ISOLATE xx PART OF 19xx
PUSHJ P,MAK2D ;MAKE INTO 2 DIGITS ASCII
MOV. T1,VYER ;STORE YEAR
MOVE T1,LOCHOR ;GET HOUR
PUSHJ P,MAKSD ;MAKE INTO 2 DIGITS
MOV. T1,VHOR ;STORE HOUR
MOVE T1,LOCMIN ;GET MINUTE
PUSHJ P,MAK2D ;MAKE INTO 2 DIGITS
MOV. T1,VMIN ;STORE MINUTES
MOVE T1,LOCSEC ;GET SECONDS
PUSHJ P,MAK2D ;MAKE INTO 2 DIGITS
MOV. T1,VSEC ;STORE SECONDS
; DECFILE11A IS ALREADY AT OFFSETS 166-176
MOVEI T1,H11BUF ;POINT AT BLOCK TO CHECKSUM
MOVEI T2,O.CHK1/2 ;COMPUTE # OF WORDS TO CHECKSUM
PUSHJ P,CHKSUM ;COMPUTE CHECKSUM
STOR. T1,CHK1 ;STORE IT
MOVEI T1,H11BUF ;POINT AT BLOCK TO CHECKSUM
MOVEI T2,O.CHK2/2 ;COMPUTE # OF WORDS TO CHECKSUM
PUSHJ P,CHKSUM
STOR. T1,CHK2 ;STORE THAT TOO
MOVE T1,H11LBN ;GET ADDRESS OF HOME BLOCK
PUSHJ P,SUSET ;POSITION TO FILES11 HOME BLOCK
OUT VIO,[IOWD 200,H11BUF
0]
SKIPA
ERROR <OUTPUT error writing FILES-11 home block>
POPJ P,
; SUBROUTINE TO DECIDE ON A VOLUME LABEL AND INSERT IT INTO HOME BLOCK
MAKLAB: PUSHJ P,SAVE2 ;SAVE 2 ACS
MOVE T1,.FXNAM(FP) ;GET 1ST HALF OF FILENAME
MOVE T2,.F2NAM(FP) ;GET 2ND HALF OF FILENAME
JUMPN T1,MAKLA1 ;BRANCH IF WE HAVE A LABEL
JUMPN T2,MAKLA1 ;BRANCH IF WE HAVE LEADING SPACE
POPJ P, ;DON'T LABEL UNLESS SPECIFIC REQUEST
MAKLA1: DMOVE P1,T1 ;SAVE THE NAME FOR LATER
MOVE T3,[O.VNAM,,A.VNAM] ;POINT AT 1ST VOLUME NAME
PUSHJ P,PUTSIX ;GO PUT IN SIXBIT STRING
DMOVE T1,P1 ;RESTORE THE NAME FROM BEFORE
MOVE T3,[O.INDN,,A.INDN] ;POINT AT 2ND VOLUME NAME
PUSHJ P,PUTSIX ;PUT IT HERE TOO
POPJ P,
; SUBROUTINE TO INSERT A 2WORD SIXBIT STRING INTO PDP11 TEXT FIELD
PUTSIX: PUSHJ P,SAVE4 ;SAVE SOME ACS
DMOVE P1,T1 ;COPY THE 2 WORD NAME
SETZ P3, ;END WITH A GUARENTEED ZERO
MOVE P4,[POINT 6,P1] ;POINT AT THE TEXT
MOVE T1,T3 ;COPY THE BYTE POINTER
PUTSI1: ILDB T3,P4 ;GET NEXT TEXT BYTE
JUMPE T3,CPOPJ ;ALL DONE IF NO MORE TEXT
ADDI T3," " ;CONVERT TO UPPER CASE ASCII
JSR PUTBYT ;INSERT THE BYTE
JRST PUTSI1 ;LOOP
SUBTTL ROUTINES TO MANAGE THE INDEX FILE
; THE INDEX CONSISTS OF TWO PARTS, THE INDEX-BIT-MAP AND
; THE INDEX-LIST.
;
; THE FILE INDEXF.SYS[0,0] CONSISTS OF THE BOOT BLOCK (BLOCK0),
; THE HOME BLOCK, AND THE INDEX-BIT-MAP AND INDEX-LIST.
;
; THE INDEX-BIT-MAP IS A BIT MAP WITH ENOUGH BITS TO REPRESENT
; EACH POSSIBLE FILE-HEADER-BLOCK. THE NUMBER OF FILE-HEADER-BLOCKS
; PERMITTED IN A VOLUME IS IN THE H.MAXF WORD IN THE VOLUME HOME BLOCK.
;
; EACH BLOCK IN THE INDEX-BIT-MAP ("IBM") CAN REPRESENT 4096 FHBS.
; NO VOLUME CAN HAVE MORE THAN 15 BITS WORTH OF FILES, SO NO IBM
; CAN BE LARGER THAN (2**15)/4096 = 8 BLOCKS.
;
; THE INDEX-LIST CONSISTS OF ALL THE FILE HEADER BLOCKS. IF A FHB
; IS ACTUALLY BEING USED FOR A FILE, THEN THE CORRESPONDING BIT IN
; THE IBM IS A "1". (THUS, THE IBM "SAT" USES OPPOSITE LOGIC TO
; THE SBM "SAT").
;
; THE FIRST 5 BLOCKS OF THE INDEX-LIST MUST BE PHYSICALLY CONTIGUOUS
; WITH THE IBM BLOCKS, BECAUSE THEY ARE USED TO FIND THE "KNOWN FILES".
;
; THE REMAINDER OF THE INDEX-LIST MAY BE SCATTERED THROUGHOUT THE
; FILES-11 VOLUME. ORDINARYILY ONLY ENOUGH BLOCKS ARE ALLOCATED TO
; THE INDEX-LIST TO ACCOUNT FOR THE FHBS IN USE (PLUS A SMALL ADDITIONAL
; NUMBER TO REDUCE OVERHEAD). FILE NUMBERS ARE ALWAYS ALLOCATED FROM
; THE IBM USING THE LOWEST FREE NUMBER.
;
; THE KNOWN FILES ARE GIVEN FILE NUMBERS OF 1 THROUGH 5.
;
; FILE#1 INDEXF.SYS
; FILE#2 BITMAP.SYS THE STORAGE-ALLOCATION-BIT-MAP
; FILE#3 BADBLK.SYS A FILE WHOSE RETRIEVAL POINTERS ARE BAD BLOCKS
; FILE#4 000000.DIR A DIRECTORY FILE HOLDING THE KNOWN FILES
; FILE#5 CORIMG.SYS A FILE WITH (POSSIBLY) AN IMAGE OF THE MONITOR
; ROUTINE TO MAKE AN INDEX BIT MAP FROM SCRATCH
MAKIBM: LOAD. T1,FMAX ;LOAD T1=MAX# OF FHBS (FROM HOME BLOCK)
IDIVI T1,^D4096 ;LOAD T1=# BLOCKS IN IBM...
;...BY DIVING MAX# FHBS/#BITS PER BLOCK
CAIE T2,0 ;SKIP IFF NO REMAINDER
ADDI T1,1 ;COUNT ONE MORE BLOCK TO COVER OVERAGE
IMULI T1,200 ;CONVERT T1=#PDP10 WORDS FOR IBM
MOVEM T1,IBMSIZ ;REMEMBER #PDP10 WORDS FOR INCORE IBM
PUSHJ P,GETCOR ;GET MEMORY FOR INCORE IBM
MOVEM T1,IBMINC ;REMEMBER ADDRESS OF INCORE IBM
SETZM MFDDAT ;INITIALIZE THE DATA IN 000000.DIR
MOVE T1,[MFDDAT,,MFDDAT+1] ;...
BLT T1,MFDDAT+177 ;...
POPJ P, ;RETURN
; ROUTINE TO WRITE THE INCORE IBM ONTO DISK (IE: INTO INDEXF.SYS)
WRTIBM: MOVE T1,IBMLBN ;LOAD T1=LBN OF ONDISK IBM
PUSHJ P,SUSET ;POSITION DISK
HRRZ T1,IBMSIZ ;LOAD T1=SIZE OF MAP IN PDP10 WORDS
IMUL T1,[-1,,0] ;CONVERT T1=AOBJN INTO MAP
HRR T1,IBMINC ;INSERT RH(T1)=POINTER TO MAP DATA
SUBI T1,1 ;CONVERT T1=IOWD INTO MAP DATA
SETZ T2, ;LOAD T2=ENDING IOWD
OUT VIO,T1 ;XFER MAP DATA TO DISK
POPJ P, ;RETURN IF I/O WAS GOOD
ERROR <OUT failed to write IBM>
; ROUTINE TO READ THE IBM INTO CORE
REDIBM: MOVE T1,IBMLBN ;LOAD T1=LBN OF ONDISK IBM
PUSHJ P,SUSET ;POSITION DISK
MOVE T1,IBMSIZ ;GET SIZE OF IBM IN WORDS
PUSHJ P,GETCOR ;ALLOCATE CORE FOR IT
MOVEM T1,IBMINC ;SAVE ADDRESS OF INCORE IBM
MOVE T1,IBMSIZ ;GET SIZE OF IBM IN WORDS
IMUL T1,[-1,,0] ;MAKE INTO IOWD COUNT
HRR T1,IBMINC ;INSERT ADDRESS
SUBI T1,1 ;IOWDIZE THE ADDRESS FIELD
SETZ T2, ;END THE IOWD LIST
IN VIO,T1 ;READ THE IBM INTO CORE
SKIPA ;SKIP IF I/O WAS GOOD
ERROR <I/O error reading Index-bit-map>
MOVEI T3,0 ;START FILE COUNT AT 0
HRRZ T1,IBMINC ;GET POINTER TO INCORE IBM
HRLI T1,(POINT 1,0) ;CONVERT TO BYTE POINTER
MOVE T2,IBMSIZ ;GET # OF WORDS IN IBM
IMULI T2,^D36 ;COMPUTE MAX # OF BITS
REDIB2: ILDB T4,T1 ;READ A BIT FROM IBM
CAIE T4,0 ;SKIP IF FILE IS FREE
ADDI T3,1 ;COUNT A FILE IN USE
SOJG T2,REDIB2 ;LOOP FOR ALL POSSIBLE FILES
LOAD. T1,FMAX ;GET MAX POSSIBLE FILES
SUB T1,T3 ;COMPUTE # OF FREE FILES
MOVEM T1,FHBTAL ;SAVE # OF FREE FIELS
POPJ P, ;RETRN
; ROUTINE TO ALLOCATE A FILE #
ALCFHB: PUSHJ P,SAVE1 ;SAVE P1
MOVE P1,T1 ;COPY INITIAL FILE NUMBER REQUESTED
LOAD. T3,FMAX ;LOAD T3=MAX# OF FILES
MOVE T2,T3 ;COPY T2=MAX FILE #
IMUL T3,[-1,,0] ;CONVERT T3=AOBJN COUNTER OF FILES
HRRI T3,1 ;INSERT RH(T3)=1ST FILE NUMBER
CAIE T1,0 ;USE 1 IF 0
CAIL T1,(T2) ;USE 1 IF ILLEGAL REQUEST
SKIPA
HRRI T3,(T1) ;USE REQUEST IF LEGAL
ALCFH1: MOVEI T1,-1(T3) ;LOAD T1=CORRESPONDING BIT# OF FILE (T3)
IDIVI T1,^D32 ;LOAD T1=WORD#, T2=BIT#
ADD T1,IBMINC ;CONVERT T1=ADDRESS OF CORRECT BIT
MOVE T2,B32TBL(T2) ;CONVERT T2=BIT MASK
TDNE T2,@T1 ;SKIP IF THIS FILE# (IE: FHB) IS FREE
AOBJN T3,[JUMPE P1,ALCFH1 ; BRANCH IF NONSPECIFIC REQUEST
ERROR <Requested file-number already in use>]
JUMPGE T3,[ERROR <No free file numbers>]
ORM T2,@T1 ;GRAB THE FHB INDEX NOW
MOVEI T1,(T3) ;LOAD T1=FILE # WE KNOW TO BE FREE
POPJ P, ;RETURN WITH T1=FREE FILE #
; ROUTINE TO "RETURN AN RHB"
; T1/ FHB BUFFER ADDRES
;
; THIS ROUTINE RETURNS ALL THE BLOCKS ALLOCATED TO THE FILE WHOSE FHB
; IS IN T1, AND THEN RETURNS THE FHB BLOCK BASED ON THE FILE# IN THE FHB.
; **THE CALLER IS RESPONSIBLE FOR UPDATING ANY DIRECTORIES THAT
; **MIGHT POINT AT THIS FHB!!
RETFHB: PUSHJ P,SAVE4 ;SAVE P1,P2
RETFH0: MOVE P1,T1 ;COPY P1=FHB BUFFER ADDRESS
SUBI P1,FHBBUF ;COMPUTE PDP10 OFFSET
IMULI P1,4 ;AND THEN COMPUTE PDP11 OFFSET
MOVE P4,P1 ;COPY PROPER OFFSET
LOAD. T1,FNUM,P1 ;GET FILE NUMBER
SUBI T1,1
IDIVI T1,^D32 ;
ADD T1,IBMINC ;MAKE P1=ADDRESS OF WORD WITH CORRECT BIT
MOVE T2,B32TBL(T2) ;MAKE P2=BIT MASK
TDNN F,[X%SUPER] ;DO NOT DEALLOCATE THE RE-USED FHB
ANDCAM T2,@T1 ;TURN OFF BIT FOR THIS FHB
LOAD. T3,USE,P1 ;GET T3=# POINTERS IN USE
JUMPE T3,CPOPJ ;EXIT IF A NULL FILE
MOVE P3,T3 ;COPY P3=T3, # POINTERS IN USE
LSH P3,-1 ;MAKE P3=# PAIRS IN USE
RETFH1: LOAD. T4,RCNT,P1 ;GET # OF BLOCKS IN THIS PAIR
ADDI T4,1 ;MAKE T1=TRUE # OF BLOCKS
LOAD. T1,RLBN,P1 ;GET LOW LBN
LOAD. T2,HRET,P1 ;GET HIGH LBN
LSH T2,^D16 ;MAKE ROOM FOR LOW LBN
OR T1,T2 ;T1=FINAL LBN
PUSHJ P,GIVSBM ;GIVE THAT BLOCK BACK
SOJG T4,[AOJA T1,.-1] ;RETURN ALL BLOCKS IN THAT POINTER
ADDI P1,4 ;STEP TO NEXT RETRIEVAL PAIR
SOJG P3,RETFH1 ;LOOP AND RELEASE THOSE BLOCKS TOO
LOAD. T1,CLL,P4 ;GET CORE LINK LOW
LOAD. T2,CLH,P4 ;GET CORE LINK HIGH
LSH T2,^D16 ;POSITION CORE LINK HIGH
OR T1,T2 ;MERGE SO THAT T1=CORE LINK ADDRESS
JUMPN T1,RETFH0 ;BRANCH TO RELEASE NEXT SEG, IF ANY
POPJ P,
; ROUTINE TO INITIALIZE THE FILE HEADER BUFFER
; T1/ FILE #
; T2/ FHB BUFFER ADDRESS
INIFHB: PUSHJ P,SAVE2 ;SAVE SOME ACS
DMOVE P1,T1 ;P1=FILE #, P2=FHB BUFFER
TDO F,[X%DEX] ;DON'T CHAIN THE FHBS DURING THE READ
PUSHJ P,REDFHB ;READ IN OLD COPY OF FHB
TDZ F,[X%DEX] ;ALLOW CHAINING AGAIN
MOVEI T2,(P2) ;COPY FHB BUFFER ADDRESS
SUBI P2,FHBBUF ;CREATE PDP10 OFFSET
IMULI P2,4 ;...AND THEN PDP11-IZE THAT
LOAD. T1,FSEQ,P2 ;LOAD OLD SEQUENCE #
SETZM (T2) ;START TO ZERO IT OUT
HRLI T2,(T2) ;COPY ADDRESS
ADDI T2,1 ;TURN INTO BLT POINTER
MOVEI T3,176(T2) ;POINT AT LAST FHB WORD
BLT T2,(T3) ;ZERO THE INITIAL FHB
ADDI T1,1 ;BUMP SEQ # UP ONE
STOR. T1,FSEQ,P2 ;INSERT INTO THE FHB
STOR. [M.IDOF],IDOF,P2 ;INIT ID AREA OFFSET
STOR. [M.MPOF],MPOF,P2 ;INIT MAP AREA OFFSET
STOR. P1,FNUM,P2 ;INIT FILE #
CAIG P1,5 ;SKIP IFF NOT A SYSTEM FILE
STOR. P1,FSEQ ;FOR KNOWN FILES, MAKE SEQ#=FILE#
STOR. [M.FLEV],FLEV,P2 ;INIT STRUCTURE LEVEL
STOR. [1],PROG,P2 ;INIT PROGRAMMER NUMBER=1
STOR. [1],PROJ,P2 ;INIT PROJECT NUMBER=1
STOR. [M.FPRO],FPRO,P2 ;INIT FILE PROTECTION
STOR. [1],FVER,P2 ;INIT VERSION=1
STOR. [M.MAX],MAX,P2 ;INITIALIZE MAX # OF RET PAIRS
MOVE T1,[O.CRDT,,A.CRDT] ;POINT AT CREATION DATE
MOVE T2,P2 ;GET OFFSET
IDIVI T2,4 ;GET BACK WORDS
ADDI T2,FHBBUF ;AND RELOCATE IT
DATE T3, ;GET DATE RIGHT NOW
PUSHJ P,STODAT ;STORE THE CURRENT DATE
MOVE T1,[O.CRTI,,A.CRTI] ;PDP11 BYTE POINTER
MOVE T2,P2 ;COPY OFFSET
IDIVI T2,4
ADDI T2,FHBBUF
MSTIME T3, ;GET TIME
IDIVI T3,^D1000*^D60 ;CONVERT TO MINUTES
PUSHJ P,STOTIM ;GO STORE IT
STOR. [1],CTSZ,P2 ;INIT "COUNT FIELD" = (ALWAYS) 1 BYTE
STOR. [3],LBSZ,P2 ;INIT "ADDRESS FIELD"= (ALWAYS) 3 BYTES
POPJ P, ;RETURN
; ROUTINE TO READ A FILE-HEADER-BLOCK INTO THE BUFFER
; FOR EXTENDED FHBS, CREATE A LINKED LIST OF FHBS, LINKED
; VIA A CORE ADDRESS STUFFED INTO CLH(HIGH), AND CLL(LOW)
; CL ("CORE LINK") LIVES INSIDE THE UNDOCUMENTED BYTES IN THE
; USER-FILE-ATTRIBUTES SECTION OF THE FHB.
;ENTER:
; T1/ FILE # OF FILES-11 FHB (PRIME RIB)
; T2/ ADDRESS OF BUFFER TO READ IT INTO
REDFHB: PUSH P,T2 ;SAVE BUFFER ADDRESS
SKIPE BUF111 ;READ INDEXF YET?
CAIG T1,5 ;OR SYSTEM FILE?
JRST [ADD T1,FHBLBN ;IF NO INDEXF OR IF KNOWN FILE
SOJA T1,REDFH1] ;...THEN TAKE EASY PATH
MOVEI T2,2(T1) ;COPY FHB AND CONVERT TO INDEXF BLOK#
LOAD. T3,IBSZ ;GET SIZE OF IBM
ADD T2,T3 ;ADD SIZE OF IBM TOO
SUBI T2,1 ;BUT FILE#S START AT 1, NOT ZERO
MOVEI T1,BUF111
PUSHJ P,SCNRET ;FIND IT IF POSSIBLE
JRST REDFH3 ;BRANCH IF SCNRET FAILED
REDFH1: PUSHJ P,SUSET ;POSITION DISK
MOVE T1,(P) ;GRAB BUFFER ADDRESS
HRLI T1,-200 ;WANT 200 WORDS
SUBI T1,1 ;USE IOWD FORMAT FOR THE ADDRESS
SETZ T2,
IN VIO,T1 ;READ THE BLOCK INTO THE BUFFER
JRST REDFH2 ;BRANCH IF I/O WAS GOOD
ERROR <I/O error reading FHB>
REDFH2: POP P,T2 ;RESTORE BUFFER ADDRESS
SUBI T2,FHBBUF ;CONSTRUCT OFFSET FROM FHB BUFFER
IMULI T2,4 ;CONVERT OFFSET TO PDP11 STYLE
LOAD. T3,EFNU,T2 ;GET EXT FILE NUMBER
TDZE F,[X%DEX] ;SKIP IF CHAINING NOT DISABLED
SETZ T3, ;PREVENT CHAINING IF DISALLOWED
STOR. T3,CLL,T2 ;INITIALIZE CORE LINK TO ZEROES
STOR. T3,CLH,T2 ;...
JUMPE T3,CPOPJ ;EXIT IF NO MORE SEGMENTS
MOVEI T1,200 ;GET PDP10 SIZE OF BLOCK
PUSHJ P,GETCOR ;GO GET THAT CORE FOR NEXT FHB SEGMENT
PUSH P,T1 ;SAVE CORE ADDRESS
STOR. T1,CLL,T2 ;STORE LOW CORE LINKE
LSH T1,-^D16 ;POSITION FOR HIGH PART
STOR. T1,CLH,T2 ;STORE HIGH CORE LINK
POP P,T1 ;RESTORE CORE ADDRESS
MOVE T2,T1 ;COPY ADDRESS OF BUFFER FOR NEXT FHB
MOVE T1,T3 ;LOAD FILE NUMBER OF NEXT SEGMENT TO READ
JRST REDFHB ;CONTINUE BY READING NEXT SEGMENT
;HERE IF SCNRET CAN'T FIND THE FHB WE WANT.
;THIS CAN BE POSSIBLE IFF WE'RE READING AN "OLD" FHB TO UPDATE THE
; SEQ#. IN THAT CASE, IT PROBABLY JUST MEANS WE'RE PEEKING INTO
; UNALLOCATED INDEXF SPACE WITH A NEW FILE. JUST RETURN AN "FHB" OF ZEROES.
REDFH3: TDNN F,[X%DEX] ;SKIP IF WE'RE JUST READING OLD COPY
ERROR <SCNRET failed to find INDEXF block>;COMPLAIN IF THIS IS REAL
MOVE T1,(P) ;GET BUFFER ADDRESS
SETZM (T1) ;START 1ST WORD AT ZEROES
HRLS T1 ;INSERT START,,0
HRRI T1,1(T1) ;MAKE IT 1ST,,2ND
MOVEI T2,176(T1) ;COMPUTE LAST WORD
BLT T1,(T2) ;ZERO THE BUFFER
JRST REDFH2 ;JOIN COMMON CODE
; ROUTINE TO WRITE A "USER" FILE-HEADER-BLOCK
;
; T1/ POINTER TO BUFFER TO WRITE
WRUFHB: PUSHJ P,SAVE4 ;SAVE SOME ACS
WRUFH4: MOVE P1,T1 ;SAVE POINTER
MOVE P2,P1 ;SAVE ANOTHER COPY OF POINTER TO BUFFER
SUBI P1,FHBBUF ;CONVERT TO OFFSET POINTER
IMULI P1,4 ;COMPUTE OFFSET IN TERMS OF PDP11 BYTES
WRUFH0: LOAD. T1,FNUM,P1 ;GET FILE #
SUBI T1,1 ;START AS IF FILE#S BEGAN AT 0
JUMPL T1,[ERROR <Illegal file number 0>]
IDIVI T1,^D32 ;COMPUTE T1=WORD#, T2=BIT#
ADD T1,IBMINC ;COMPUTE T1=WORD ADDRESS
MOVE T2,B32TBL(T2) ;LOAD T2=BIT MASK
ORM T2,@t1 ;TURN ON BIT FOR THIS FHB
;HERE TO INSERT A REVISION DATE AND TO "BUMP" THE REVISION NUMBER
; N.B.: IF YOU ARE UNLUCKY, YOU COULD GET TODAYS DATE AND TOMOROWS TIME
MOVE T1,[O.RVDT,,A.RVDT] ;MAKE PDP11 BYT POINTER
MOVE T2,P1 ;COPY FHB
IDIVI T2,4 ;/4
ADDI T2,FHBBUF ;COMPUTE CORRECT ADDRESS
DATE T3, ;GET DATE AS OF RIGHT NOW
PUSHJ P,STODAT ;STORE RIGHT NOW DATE INTO FHB
MOVE T1,[O.RVTI,,A.RVTI] ;GET PDP11 BYTE POINTER TO REVISE TIME
MOVE T2,P1 ;COPY OFFSET
IDIVI T2,4 ;GET PDP11 OFFSEt
ADDI T2,FHBBUF ;COMPUTE FHB ADDRESS
MSTIME T3, ;GET TIME OF DAY ASOF RIGHT NOW
IDIVI T3,^D1000*^D60 ;COMPUTE SECONDS
PUSHJ P,STOTIM ;STORE SECONDS PAST MIDNITE
LOAD. T2,FNUM,P1 ;GET FILE NUMBER
LOAD. T1,RVNO,P1 ;GET OLD REVISION NUMBER
ADDI T1,1 ;UP IT BY ONE
CAIG T2,5 ;SKIP IF NOT A KNOWN FILE
PUSHJ P,[SETZ T1, ;SET REV#=0 IF SYSTEM FILE
STOR. T2,FSEQ,P1 ;SET SEQ#=FILE# IF SYSTEM FILE
POPJ P,0] ;
STOR. T1,RVNO,P1 ;STORE NEW REVISION NUMBER
LOAD. T1,FNUM,P1 ;GET FILE #
MOVEI T2,2(T1) ;...
LOAD. T3,IBSZ ;GET SIZE OF IBM
ADD T2,T3 ;ADD SIZE OF IBM, TOO
SUBI T2,1 ;IBM#S START AT 0
MOVEI T1,BUF111 ;POINT AT FHB HAVING INDEXF.SYS IN IT
PUSHJ P,SCNRET ;SCAN FOR THAT BLOCK
JRST WRUFH2 ;DARN - MUST EXTEND INDEXF.SYS FIRST
PUSHJ P,SUSET ;POSITION DISK
LOAD. T1,CLL,P1 ;GET CORE LINK LOW
PUSH P,T1 ;SAVE CORE LINK LOW
LOAD. T1,CLH,P1 ;GET CORE LINK HIGH
PUSH P,T1 ;SAVE CORE LINK HIGH
STOR. [0],CLL,P1 ;ZERO CORE LINK LOW
STOR. [0],CLH,P1 ;ZERO CORE LINK HIGH
MOVEI T1,(P2) ;COPY ADR OF INCORE FHB
MOVEI T2,O.CKSM/2 ;LOAD T2=SIZE OF CHECKSUM AREA
PUSHJ P,CHKSUM ;DO CHECKSUM OF INCORE FHB
STOR. T1,CKSM,P1 ;INSERT CHECKSUM INTO FHB
HRLI P2,-200 ;INSERT WORD COUNT
SUBI P2,1 ;CONVERT TO DF10 FORMAT
SETZ P3, ;END THE IOWD LIST
OUT VIO,P2 ;WRITE OUT HIS FHB
JRST WRUFH3 ;DONE - GO WRITE REMAINING FHBS
ERROR <I/O error writing FHB>
;HERE TO EXTEND THE SIZE OF INDEXF.SYS SO THAT WE CAN WRITE THE FHB INTO IT
WRUFH2: TYPE <% Extending INDEXF.SYS
>
MOVEI T1,M.INFH ;GET INCREMENTAL SIZE TO EXPAND BY
PUSHJ P,SCNSBM ;TRY TO GET IT
ERROR <Cannot extend INDEXF.SYS to assign disk space to the FHB>
CAILE T1,M.INFH
MOVEI T1,M.INFH
MOVEI T3,BUF111 ;POINT AT INDEXF.SYS FHB
PUSHJ P,ZERRET ;ZERO THE BLOCKS FIRST
PUSHJ P,STORET ;INSERT THE NEW POINTER
MOVEI T1,BUF111 ;POINT AT INDEXF.SYS FHB
PUSHJ P,WRUFHB ;CALL OURSELVES TO REWRITE INDEXF.SYS
JRST WRUFH0 ;NOW TRY AGAIN TO WRITE REAL FHB
; HERE TO WRITE REMAINING FHBS
WRUFH3: POP P,T1 ;GET BACK HIGH
STOR. T1,CLH,P1 ;RESTORE IT
POP P,T2 ;GET BACK LOW
STOR. T2,CLL,P1 ;RESTORE IT
LSH T1,^D16 ;POSITION HIGH
OR T1,T2 ;POINT AT NEXT FHB, IF ANY
JUMPN T1,WRUFH4 ;AND LOOP TO WRITE THE NEXT
POPJ P, ;ALL DONE IF NO MORE FHBS
; ROUTINE TO WRITE THE FILE-HEADER-BLOCK BUFFER ONTO CORRECT DISK BLOCK
WRTFHB: MOVEI T1,FHBBUF ;SETUP TO WRITE ALWAYS FROM FHBBUF
PUSHJ P,WRUFHB ;WRITE OUT FHBBUF + EXTENSIONS
LOAD. T2,FNUM ;GET FILE NUMBER AGAIN
SUBI T2,1 ;FILE#S START AT 1 NOT 0
IMULI T2,20 ;TIMES # OF BYTES PER ENTRY
LOAD. T1,FNUM ;GET FILE #
STOR. T1,UFNO,T2 ;STOR INTO MFD DATA
LOAD. T1,FSEQ ;GET SEQ#
STOR. T1,UFSQ,T2 ;STORE INTO MFD
LOAD. T1,FNAM
STOR. T1,UFNM,T2
LOAD. T1,FTYP
STOR. T1,UFTY,T2
LOAD. T1,FVER
STOR. T1,UVER,T2
POPJ P,0
; ROUTINE TO "TYPE" AN FHB POINTED TO BY (T1)
TYPFHU: TDOA F,[X%UIC] ;FLAG WE WANT TO STOP AFTER UIC FIELD
TYPFHB: TDZ F,[X%UIC] ;FLAG WE WANT ALL POSSIBLE INFO
PUSHJ P,SAVE4 ;SAVE SOME ACS
TYPFHJ: MOVE P1,T1 ;COPY THE FHB ADDRESS
MOVE P2,P1 ;SAVE ORIGINAL TOO
SUBI P1,FHBBUF ;COMPUTE OFFSET...
IMULI P1,4 ;...IN TERMS OF PDP11 BYTES
LOAD. T1,CLL,P1 ;GET CORE LINK LOW
PUSH P,T1 ;SAVE CORE LINK LOW
LOAD. T1,CLH,P1 ;GET CORE LINK HIGH
PUSH P,T1 ;SAVE IT
SETZ T1, ;GET A ZERO
STOR. T1,CLL,P1 ;ZERO CORE LINK LOW
STOR. T1,CLH,P1 ;ZERO CORE LINK HIGH
MOVEI T1,(P2) ;LOAD T1=FHB ADR
MOVEI T2,O.CKSM/2 ;T2=# OF WORDS TO CHECKSUM
PUSHJ P,CHKSUM ;GO VERIFY FHB'S CHECKSUM WORD
LOAD. T2,CKSM,P1 ;GET CHECKSUM
CAME T1,T2 ;SKIP IF COMPUTE MATHES COPY IN FHB
TYPE <% FHB Checksum error on:
>
POP P,T1 ;RESTORE CORE LINK LOW
STOR. T1,CLH,P1 ;RESTORE IT
POP P,T1 ;RESTORE CORE LINK LOW
STOR. T1,CLL,P1 ;RESTORE IT
TDNN F,[X%UIC] ;SKIP IF WANT SHORT VERSION ONLY
JRST TYPFHV ;DON'T MENTION VOLUME IF LONG VERSION
MOVE T1,DSKBLK+.DCUPN ;GET PHYSICAL UNIT IN DSKCHR BLOCK
SKIPE T2,FAKVOL ;SKIP IF REAL VOLUME
MOVE T1,VOLTBL(T2) ;GET FAKE VOLUME NAME
PUSHJ P,SIXOUT ;TYPE VOLUME NAME
TYPE <:> ;TYPE SEPERATOR
DMOVE T1,UFDNAM ;GET DIRECTORY NAME
PUSHJ P,TYPDIN ;TYPE DIRECTORY NAME
TYPFHV: LOAD. T1,FNM1,P1 ;GET 1ST WORD OF FILE NAME
; PUSHJ P,RAD53O ;TYPE IT
LOAD. T2,FNM2,P1 ;GET 2ND WROD OF FILE NAME
; PUSHJ P,RAD53O ;TYPE IT
LOAD. T3,FNM3,P1 ;GET 3RD WORD OF FILE NAME
; PUSHJ P,RAD53O ;TYPE IT
PUSHJ P,FILE5O ;TYPE OUT FILE NAME
TYPFHZ: TYPE <.>
LOAD. T1,FTYP,P1
PUSHJ P,RAD53O ;TYPE IT
TYPE <;>
LOAD. T1,FVER,P1 ;GET VERSION #
PUSHJ P,OCTOUT ;TYPE IT
TDNE F,[X%UIC]
POPJ P,
MOVEI T1,^D21 ;COLUMN 21 STARTS SIZE FIELD
PUSHJ P,MOVCOL ;GO THERE
MOVE T1,P2 ;COPY POINTER TO FHB
PUSHJ P,GETALC ;GET ALLOCATION FOR THIS (ENTIRE) FILE
LOAD. T2,ESQN,P1 ;GET THIS "RIB NUMBER"
SKIPN T2 ;COUNT ONLY THE PRIME RIB BLOCKS
ADDM T1,TOTBLK
PUSHJ P,DECO5 ;ALLOW 5 DIGITS
TYPE < >
LOAD. T1,UCHA,P1 ;GET USER CHARACTERISTICS
TRNE T1,UC.CON ;CONTIGUOUS?
TYPE <C> ;YES, SAY SO
TRNN T1,UC.CON ;?
TYPE < > ;NO
TRNE T1,UC.DLK ;IMPROPERLY CLOSED?
TYPE <I> ;YES, SAY SO
TRNN T1,UC.DLK ;?
TYPE < > ;
LOAD. T1,SCHA,P1 ;GET SYSTEM CHARS
TRNE T1,SC.MDL ;MARKED FOR DELETE?
TYPE <D> ;YES, SAY SO
TRNN T1,SC.MDL
TYPE < >
TRNE T1,SC.BAD
TYPE <B>
TRNN T1,SC.BAD
TYPE < >
MOVEI T1,(P2)
PUSHJ P,TYPCDT
MOVEI T1,(P2)
PUSHJ P,TYPRDT
MOVEI T1,(P2)
PUSHJ P,TYPXDT
PUSHJ P,CRLF
MOVE T1,.FXSWT(FP)
TDNN T1,[S$DETAIL] ;/DETAIL?
POPJ P, ;RETURN
PUSHJ P,TYPUNT ;TYPE INFO FROM UFD ENTRY
PUSHJ P,TYPHID ;TYPE INFO FROM HEADER
PUSHJ P,TYPLEV ;TYPE OUT FILE LEVEL
PUSHJ P,TYPESI ;TYPE EXTENSION SEGMENT INFO
PUSHJ P,TYPUFA ;TYPE THE USER FILE ATTRIBUTES
PUSHJ P,TYPFMA ;TYPE THE FILE MAP AREA DATA
LOAD. T1,CLL,P1 ;GET LOW CORE LINK
LOAD. T2,CLH,P1 ;GET HIGH CORE LINK
LSH T2,^D16 ;POSITION HIGH LINK
OR T1,T2 ;MERGE FOR TOTAL CORE LINK
JUMPN T1,TYPFHJ ;BRANCH TO TYPE NEXT SEGMENT
POPJ P, ;DONE
;ROUTINE TO TYPE THE FILE'S FILES-11 VERSION LEVEL
TYPLEV: TYPE < File structure level: >
LOAD. T1,FLEV,P1
PUSHJ P,OCTOUT
JRST CRLF
;ROUTINE TO TYPE EXTENSION SEGMENT INFO
TYPESI: TYPE < Extension segment number:>
LOAD. T1,ESQN,P1 ;GET SEGMENT NUMBER
PUSHJ P,DECOUT ;TYPE SEGMENT NUMBER IN DECAL
TYPE <, extension number,sequence (>
LOAD. T1,EFNU,P1 ;GET FILE NUMBER
PUSHJ P,DECOUT ;TYPE FILE NUMBER
TYPE <,> ;SEPERATE
LOAD. T1,EFSQ,P1 ;GET SEQUENCE
PUSHJ P,DECOUT ;TYPE FILE NUMBER
TYPE <)>
JRST CRLF ;GIVE BLANK LINE AND EXIT
;ROUTINE TO TYPE A "DIRECTORY NAME"
TYPDIN: PUSHJ P,SAVE2 ;SOME SOME ACS
TYPE <[> ;ENCLOSE DIRECTORY IN []S
DMOVE P1,T1 ;PRESERVE THEM
JUMPN T2,TYPDI1 ;BRANCH IF 2 WORDS OF TEXT IN DIRECTORY
PUSHJ P,QC6T8 ;GO CONVERT 1ST AND ONLY WORD TO OCTAL
JRST TYPDI1 ;BRANCH IF NOT AN OCTAL NUMBER
TDNE T1,[-1,,400400] ;BRANCH IF NOT BEYOND "UIC" RANGE
JRST TYPDI1 ;BRANCH IF BEYOND UIC RANGE
MOVE P1,T1 ;SAVE THE NUMBER
LDB T1,[POINT 8,T1,26] ;GET FIRST PART
PUSHJ P,OCTOUT ;TYPE FIRST PART
TYPE <,> ;SEPERATE IT
LDB T1,[POINT 8,P1,35] ;GET SECOND PART
PUSHJ P,OCTOUT ;TYPE SECOND PART
TYPE <]> ;CLOSE IT
POPJ P, ;AND EXIT
TYPDI1: MOVE T1,P1 ;GET FIRST HALF
PUSHJ P,SIXOUT ;TYPE FIRST HALF
SKIPE T1,P2 ;SKIP IF NO SECOND HALF
PUSHJ P,SIXOUT ;TYPE SECOND HALF IF PRESENT
TYPE <]> ;CLOSE IT
POPJ P, ;AND EXIT
; ROUTINE TO TYPE INFORMATION FROM UFD ENTRY
TYPUNT: SKIPN INPFDB+.FXNAM
POPJ P, ;FORGET IT IF INDEX COMMAND
TYPE < From Directory: >
MOVE T1,INPFDB+.FXNAM
PUSHJ P,SIXOUT
SKIPE T1,INPFDB+.F2NAM
PUSHJ P,SIXOUT
HLLZ T1,INPFDB+.FXEXT
JUMPN T1,[TYPE <.>
PUSHJ P,SIXOUT
JRST .+1]
TYPE <;>
MOVE T1,INPFDB+.FXGEN
PUSHJ P,OCTOUT
TYPE <(>
MOVE T1,INPFDB+.FXNUM
PUSHJ P,R10OUT
TYPE <,>
MOVE T1,INPFDB+.FXSEQ
PUSHJ P,R10OUT
TYPE <,>
MOVE T1,INPFDB+.FXRVN
PUSHJ P,R10OUT ;TYPE GENERATION NUMBER TOO
TYPE <)>
DMOVE T1,UFDNAM ;GET DIRECTORY NAME
PUSHJ P,TYPDIN ;TYPE DIRECTORY NAME
JRST CRLF
; ROUTINE TO TYPE FILE-ID INFORMATION FROM THE FHB
TYPHID: TYPE < From Header: >
PUSHJ P,TYPFNM ;TYPE FILE NAME
PUSHJ P,TYPFID ;TYPE FILE ID
PUSHJ P,TYPOWN ;TYPE OWNER
JRST TYPPRO ;TYPE PROTECTION, CRLF, RETURN
; PUSHJ P,TYPPRO ;TYPE PROTECTION
; JRST CRLF
TYPFNM: LOAD. T1,FNM1,P1 ;GET 1ST PART OF FILE NAME
LOAD. T2,FNM2,P1 ;GET 2ND PART
LOAD. T3,FNM3,P1 ;GET 3RD PART
PUSHJ P,FILE5O ;TYPE FILE NAME
TYPE <.>
LOAD. T1,FTYP,P1
PUSHJ P,RAD53O
TYPE <;>
LOAD. T1,FVER,P1
PUSHJ P,OCTOUT
POPJ P,
; ROUTINE TO TYPE THE USER FILE PROTECTION
TYPPRO: LOAD. T1,FPRO
PUSHJ P,P11OUT
JRST CRLF
; ROUTINE TO TYPE THE FILE ID
TYPFID: TYPE <(>
LOAD. T1,FNUM,P1 ;GET FILE NUMBER
PUSHJ P,R10OUT ;TYPE IT
TYPE <,>
LOAD. T1,FSEQ,P1
PUSHJ P,R10OUT
TYPE <)>
POPJ P,
; ROUTINE TO TYPE THE FILE OWNER UIC
TYPOWN: TYPE <[>
LOAD. T1,PROJ,P1
PUSHJ P,OCTOUT
TYPE <,>
LOAD. T1,PROG,P1
PUSHJ P,OCTOUT
TYPE <]>
POPJ P,
; ROUTINE TO TYPE OUT THE FILE MAP AREA
TYPFMA: LOAD. T1,USE,P1 ;GET # OF POINTERS IN USE
JUMPE T1,TYPFM3 ;BRANCH IF NO SPACE ALLOCATED
PUSHJ P,SAVE2 ;SAVE SOME ACS
MOVE P2,P1 ;COPY FHB OFFSET IN USE
MOVE P1,T1 ;COPY TO A SAFE PLACE
LSH P1,-1 ;GET # OF PAIRS
TYPE < File mapping information:
>
TYPE < (>
MOVE T1,P1 ;GET NUMBER OF POINTER PAIRS IN USE
PUSHJ P,DECOUT ;TYPE IT
LOAD. T1,MAX ;GET MAX USABLE
JUMPE T1,TYPFM2 ;SKIP CONFUSING COMMENTARY
TYPE < of > ;
LOAD. T1,MAX ;GET THE MAX USABLE
LSH T1,-1 ;COMPUTE # POINTERS POSSIBLE
PUSHJ P,DECOUT ;
TYPFM2: TYPE < pointers used)
> ;
TYPFM1: TYPE < >
LOAD. T1,RCNT,P2 ;GET COUNT
ADDI T1,1 ;ALWAYS +1
PUSHJ P,DECO3 ;TYPE IT
TYPE < at >
LOAD. T1,RLBN,P2 ;ET LOW LBN
LOAD. T2,HRET,P2 ;GET HIGH LBN
LSH T2,^D16 ;MAKE ROOM
OR T1,T2 ;MERGE
PUSHJ P,OCTO7
PUSHJ P,CRLF
ADDI P2,4 ;ADVANCE TO NEXT PAIR
SOJG P1,TYPFM1 ;TYPE THAT TOO
PJRST CRLF
TYPFM3: TYPE < >
TYPE <File mapping information: No disk space allocated>
PUSHJ P,CRLF
PJRST CRLF
; ROUTINE TO TYPE OUT USER FILE ATTRIBUTES BLOCK
TYPUFA: TYPE < Record type = >
LOAD. T1,RTYP,P1 ;GET RECORD TYPE BYTE
PUSHJ P,OCTOUT ;TYPE IT
LOAD. T1,RTYP,P1 ;gET IT AGAIN
CAIN T1,R.FIX ;
TYPE <, fixed length records>
CAIN T1,R.VAR
TYPE <, variable non-sequenced records>
CAIN T1,R.SEQ
TYPE <, variable length sequenced records>
TYPE <
Record attributes = >
LOAD. T1,RATT,P1
PUSHJ P,OCTOUT
LOAD. T1,RATT,P1
TRNE T1,FD.FTN
TYPE <, first byte is FORTRAN-CC>
TRNE T1,FD.CR
TYPE <, implied LF before line and CR after>
TRNE T1,FD.BLK
TYPE <, records cannot span block boundries>
TYPE <
Record size = >
LOAD. T1,RSIZ,P1
PUSHJ P,DECOUT
TYPE < bytes>
TYPE <
Highest VBN allocated = >
LOAD. T1,HIBH,P1 ;
LOAD. T2,HIBL,P1
LSH T1,^D16
OR T1,T2
PUSHJ P,OCTOUT
TYPE <
EOF VBN = >
LOAD. T1,EFBH,P1
LSH T1,^D16
LOAD. T2,EFBL,P1
OR T1,T2
PUSHJ P,OCTOUT
TYPE <
First Free Byte = >
LOAD. T1,FFBY,P1
PUSHJ P,OCTOUT
TYPE <
Record Access byte = >
LOAD. T1,RACC,P1
PUSHJ P,OCTOUT
LOAD. T1,RACC,P1
TRNE T1,FD.RWM
TYPE <, READ$/WRITE$ mode>
TRNE T1,FD.RAN
TYPE < GET$/PUT$ mode>
TRNE T1,FD.PLC
TYPE <, locate mode>
TRNN T1,FD.PLC
TYPE <, move mode>
TRNN T1,FD.INS
TYPE < PUT$ truncates the file>
PJRST CRLF
; ROUTINE TO COMPUTE THE ALLOCATED BLOCKS FOR THE FILE WHOSE FHB IS (T1)
GETALC: PUSHJ P,SAVE2 ;GO SAVE SOME ACS
SETZ P1, ;ZERO TOTAL ALLOCATION
GETAL1: MOVE P2,T1 ;COPY FHB POINTER
SUBI P2,FHBBUF ;FIND OFFSET FROM FHBBUF
IMULI P2,4 ;COMPUTE PDP11 STYLE OFFSET
PUSHJ P,FNDALC ;FIND ALLOCATION IN THIS FHB (ONLY)
ADD P1,T1 ;ADD IN THIS FHB'S ALLOCATION TO TOTAL
LOAD. T1,CLL,P2 ;GET POINTER TO NEXT FHB, IF ANY
LOAD. T2,CLH,P2 ;GET HIGH POINTER TO NEXT FHB, IF ANY
LSH T2,^D16 ;POSITION HIGH PART
OR T1,T2 ;MERGE PARTS
JUMPN T1,GETAL1 ;LOOP IF ANOTHER SEGMENT TO COUNT
MOVE T1,P1 ;STORE ALLOCATION IN T1 FOR CALLER
POPJ P,
; ROUTINE TO COMPUTE ALLOCATED BLOCKS FOR THE FHB POINTED TO BY (T1)
FNDALC: PUSHJ P,SAVE1 ;SAVE AN AC
MOVE P1,T1 ;POINT AT FHB VIA P1
SUBI P1,FHBBUF ;COMPUTE OFFSET FROM FHBBUF
IMULI P1,4 ;COMPUTE PDP11 SYLE OFFSET
LOAD. T3,USE,P1 ;GET THE COUNT OF USED POINTERS
LSH T3,-1 ;CONVERT TO # OF PAIRS OF POINTERS
SETZB T1,T4 ;T1=ALLOCATED COUNT, T4=OFFSET
ADD T4,P1 ;COMPUTE OFFSET FOR MAPPING POINTERS
JUMPE T3,CPOPJ ;EXIT IF NO PAIR USED
FNDAL1: LOAD. T2,RCNT,T4 ;GET BLOCK COUNT FOR THIS PAIR
ADDI T1,1(T2) ;ADD TO THIS FHB'S TOTAL
ADDI T4,S.RETP ;ADVANCE TO NEXT POINTER PAIT
SOJG T3,FNDAL1 ;BRANCH BACK IF MORE USED POINTERS
POPJ P, ;RETURN IF ALL POINTERS SCANNED
; SUBROUTINE TO STORE A RETRIEVAL POINTER PAIR INTO THE FHB BEING BUILT
;
; T1/ # OF BLOCKS IN RETREIVAL POINTER PAIR
; T2/ 1ST LBN DESCRIBED BY PAIR
; T3/ POINT TO FHB TO CONTAIN THIS PAIR
STORET: PUSHJ P,SAVE4 ;SAVE SOME ACS
DMOVE P1,T1 ;LOAD P1=BLOCKS, P2=LBN# OF 1ST
STORE0: DMOVE P3,T3 ;LOAD P3=BUFFER ADDRESS
SUBI P3,FHBBUF ;COMPUTE P3=PDP10 OFFSET TO FHB BUFFER
IMULI P3,4 ;COMPUTE P3=PDP11 OFFSET TO FHB BUFFER
STORE3: LOAD. T1,MPOF,P3 ;LOAD T1=MAP AREA OFFSET IN WORDS
IMULI T1,2 ;CONVERT T1=MAP AREA OFFSET IN BYTES
LOAD. T2,USE,P3 ;LOAD T2=#RETRIEVAL WORDS IN USE
LOAD. P4,MAX,P3 ;GET THE NUMBER WE'RE ALLOWED TO HAVE
SKIPN P4 ;SKIP IF VALID
MOVEI P4,314 ;CONVERT TO VALID IF NEEDED
CAML T2,P4 ;ONLY ALLOW IF ROOM FOR IT
JRST STORE2 ;BRANCH IF OUT OF SLOTS IN THIS FHB
IMULI T2,2 ;CONVERT T2=#RETRIEVAL BYTES IN USE
ADDI T2,(P3) ;AND OFFSET BY FHB POINTER
MOVE T1,P1 ;LOAD T1=BLOCK COUNT FROM RETRIEVAL PAIR
SUBI T1,1 ;CONVERT T1=FORM AS APPEARS IN FHB
STOR. T1,RCNT,T2 ;STORE BLOCK COUNT INTO FHB
MOVE T1,P2 ;LOAD T1=1ST BLOCK IN GROUP
STOR. T1,RLBN,T2 ;STORE (LOW) BLOCK NUMBER INTO FHB
LSH T1,-^D16 ;ISOLATE T1=HIGH PDP11 WORD OF BLOCK #
STOR. T1,HRET,T2 ;STORE (HIGH) BLOCK NUMBER INTO FHB
LOAD. T1,USE,P3 ;LOAD T1=# OF RETRIEVAL WORDS IN USE
ADDI T1,2 ;UPDATE T1=2 MORE WORDS
STOR. T1,USE,P3 ;STORE UPDATED COUNT BACK INTO FHB
; HERE TO ENSURE THAT THE BLOCKS JUST ATTACHED ARE REMOVED FROM THE SATS
STORE1: MOVE T1,P2 ;COPY BLOCK #
PUSHJ P,TAKSBM ;GET THAT BLOCK
JFCL ;IGNORE ERROR RETURN
SOJG P1,[AOJA P2,STORE1] ;LOOP FOR ALL BLOCKS IN THE GROUP
ADDI P2,1 ;ADVANCE TO UNUSED BLOCK
MOVEM P2,FFBLOK ;REMEMBER WHICH IT WAS
POPJ P, ;RETURN
; HERE WHEN AN FHB IS OUT OF RETRIEVAL SLOTS
STORE2: LOAD. T3,CLL,P3 ;GET CORE LINK LOW
LOAD. T2,CLH,P3 ;GET CORE LINK HIGH
LSH T2,^D16 ;POSITION CORE LINK HIGH
OR T3,T2 ;MERGE SO T3=CORE LINK ADDRESS
JUMPN T3,STORE0 ;BRANCH IF ANOTHER SEGMENT TO TRY
; HERE WHEN LINKED LIST OF FHBS RUNS OUT, ALLOCATE ANOTHER
SETZ T1, ;DON'T REQUEST A SPECIFIC FILE NUMBER
PUSHJ P,ALCFHB ;ALLOCATE A FILE HEADER, NUMBER IN T1
PUSH P,T1 ;SAVE FILE NUMBER
MOVEI T1,200 ;NUMBER OF PDP10 WORDS IN FHB
PUSHJ P,GETCOR ;GET CORE FOR YET ANOTHER FHB
MOVE P4,T1 ;COPY CORE ADDRESS
STOR. T1,CLL,P3 ;POINT PREVIOUS FHB AT THIS NEW ONE
LSH T1,-^D16 ;POSITION HIGH
STOR. T1,CLH,P3 ;STORE CORE LINK HIGH IN PREVIOUS FHB
MOVE T1,P3 ;GET OFFSET
IDIVI T1,4 ;TURN BACK INTO PDP10 OFFSET
ADDI T1,FHBBUF ;TURN BACK INTO PDP10 ADDRESS
MOVSI T1,(T1) ;ORIGIN,,0
HRRI T1,(P4) ;ORIGIN,,DEST
BLT T1,177(P4) ;COPY OLD FHB INTO NEW ONE
SUBI P4,FHBBUF ;CONVERT TO OFFSET
IMULI P4,4 ;CONVERT OFFSET TO PDP11 STYLE
POP P,T1 ;RESTORE FILE NUMBER
STOR. T1,EFNU,P3 ;POINT OLD FHB AT THIS ONE
STOR. T1,FNUM,P4 ;STORE FILE NUMBER IN NEW FHB
LOAD. T1,FSEQ,P3 ;GET OLD SEQUENCE #
STOR. T1,FSEQ,P4 ;AND JUST USE THAT AS NEW ONE
STOR. T1,EFSQ,P3 ;STORE THIS SEQ AS POINTER TO NEW
STOR. [0],USE,P4 ;ZERO THE POINTER COUNT IN NEW ONE
STOR. [0],CLL,P4 ;START OFF WITHOUT A CORE LINK
STOR. [0],CLH,P4 ;...
LOAD. T1,ESQN,P3 ;GET EXT NUMBER OF OLD ONE
ADDI T1,1 ;ADD 1
STOR. T1,ESQN,P4 ;AND USE THAT AS EXT NUMBER OF NEW ONE
STOR. [0],HIBL,P4
STOR. [0],HIBH,P4
STOR. [0],EFBH,P4
STOR. [1],EFBL,P4
MOVE P3,P4 ;SWITCH TO POINT AT NEW FHB
JRST STORE3 ;AND SCAN THIS NEW FHB (WHICH MUST WIN)
; ROUTINE TO ZERO OUT THE BLOCKS DESCRIBED BY THE RETRIEVAL
; POINTER PAIR IN T1/T2. USED TO GUARANTEE THE "INITIAL" FHBS
; FOR ALL FILES START WITH SEQUENCE #0.
ZERRET: PUSHJ P,SAVE2 ;SAVE SOME ACS
DMOVE P1,T1 ;SAVE THE ENTRIES
EXCH T1,T2 ;GET T1=LBN, T2=COUNT
PUSHJ P,SUSET ;POSITION TO FIRST BLOCK
ZERRE1: OUT VIO,[IOWD 1,LOWZRO ;WRITE OUT A PADDED BLOCK OF 0S
0] ;...
SKIPA ;SKIP IF ALL OK
ERROR <Cannot zero newly acquired FHB blocks>
SOJG T2,ZERRE1 ;LOOP TILL ALL DONE
DMOVE T1,P1 ;RESTORE T1/T2
POPJ P, ;RETURN
; ROUTINE TO SCAN RETRIEVAL POINTERS
; T1/ POINTER TO FHB BUFFER
; T2/ BLOCK # TO FIND, STARTS AT 0
;
; N.B.!!! WE CONSIDER BLOCK #'S TO START AT 0 BECAUSE IT IS CONVENIENT,
; BUT RSX CONSIDERS THEM TO START AT 1!!
SCNRET: PUSHJ P,SAVE4 ;SAVE SOME ACS
MOVE P2,T1 ;COPY ADDRESS OF FHB
SUBI P2,FHBBUF ;COMPUTE PDP10 OFFSET
IMULI P2,4 ;THEN PDP11 OFFSET
SCNRE0: SETZ P1, ;LOW RELATIVE BLOCK # IN THIS GROUP
SCNRE5: LOAD. T3,USE,P2 ;P3=#OF POINTERS IN USE
MOVE P4,P2 ;SAVE OFFSET BEFORE SCANNING POINTERS
JUMPE T3,CPOPJ ;EXIT IF NO DISK SPACE ASSIGNED
MOVE P3,T3
LSH P3,-1 ;CONVERT TO # OF PAIRS
SCNRE1: LOAD. T3,RCNT,P2 ;GET COUNT FOR THIS GROUP
ADDI T3,1 ;MAKE T3=TRUE COUNT
ADD T3,P1 ;T3=1ST RELATIVE BLOK# IN NEXT GROUP
CAML T2,T3 ;GUARENTEED TO FALL IN THIS GROUP?
JRST SCNRE2 ;NO
LOAD. T3,RLBN,P2 ;GET LOW LBN FOR THIS GROUP
LOAD. T4,HRET,P2 ;GET HIGH LBN FOR THIS GROUP
LSH T4,^D16 ;MAKE ROOM FO LOW PART
OR T4,T3 ;T4=LBN OF THIS GROUP
SUB T2,P1 ;CONVERT T2=RELATIVE BLOCK# TO THIS GROUP
ADD T4,T2 ;COMPUTE T4=BLOCK #
MOVE T1,T4 ;COPY BLOK# TO T1
JRST CPOPJ1 ;GIVE GOOD RETURN
SCNRE2: MOVE P1,T3 ;LOAD FOR NEXT LOOP
ADDI P2,4 ;ADVANCE TO NEXT GROUP
SOJG P3,SCNRE1 ;KEEP TRYING
LOAD. T3,CLL,P4 ;GET CORE LINK LOW
LOAD. T4,CLH,P4 ;GET CORE LINK HIGH
LSH T4,^D16 ;POSITION HIGH
OR T3,T4 ;MERGE THE TWO
JUMPE T3,CPOPJ ;EXIT IF WE NEVER FOUND IT
MOVE P2,T3 ;GET THE ADDRESS OF NEXT FHB
SUBI P2,FHBBUF ;COMPUTE PDP10 OFFSET
IMULI P2,4 ;THEN PDP11 OFFSET
JRST SCNRE5 ;THEN SCAN THIS NEW FHB
SUBTTL ROUTINES TO MANAGE THE STORAGE-BIT-MAP
; THE STORAGE-BIT-MAP CONTROLS THE ALLOCATION OF BLOCKS WITHIN
; THE FILES-11 VOLUME SPACE.
;
; THE SBM CONSISTS OF TWO PARTS, THE "SAB" AND THE "BM".
;
; THE "SAB" BLOCK IS THE FIRST BLOCK OF THE SBM FILE.
;
; THE "SAB" CONSISTS OF ENTRIES WHICH SHOW THE CURRENT TALLY OF
; FREE UNUSED BLOCKS AVAILABLE IN EACH BLOCK OF THE "BM". THE "SAB"
; IS INDEXED BY THE "BM" BLOCK NUMBER TIMES 4.
;
; THE "BM" (BIT-MAP) PART CONTAINS ENOUGH DISK BLOCKS TO REPRESENT
; A MAP OF THE ENTIRE FILES-11 VOLUME WITH 1 BIT PER STORAGE-CLUSTER.
; SINCE THE BM IS IN "PDP11" FORMAT, EACH PDP10 WORD MAPS ONLY
; 32 CLUSTERS. EACH PDP10 BLOCK CAN THUS MAP 32*128=4096 CLUSTERS.
; THE INDEX INTO THE BIT MAP IS THE "TRUE" CLUSTER NUMBER, NOT THE
; RELATIVE CLUSTER NUMBER (IE: RELATIVE TO THE DISK'S BLOCK 0, NOT
; RELATIVE TO "DATA BLOCK 0" OF "FE.SYS").
;
; ORDINARYILY, ONLY THE LAST FEW BLOCKS OF THE BM INDICATE ANY FREE BLOCKS
; BECAUSE THE FIRST BLOCKS ARE DUMMYS FILLED TO ZEROS TO MARK THE PART
; OF THE APPARENT FILES-11 VOLUME WHICH REALLY BELONGS TO TOPS-10.
;
; IN THE BM, A "1" BIT MEANS THE CLUSTER IS FREE.
;
; THERE IS NO EVIDENCE THAT ANY PART OF RSX20F PAYS ANY ATTENTION
; TO THE SAB PORTION OF THE SBM FILE, BUT THE "INI" UTILITY SETS
; IT UP AND ALL OF RSX20F (IE: F11ACP) SEEMS TO KNOW THAT THE
; FIRST BLOCK OF THE SBM MUST BE IGNORED.
; ROUTINE TO CREATE AN INITIAL SBM FOR A FILES-11 VOLUME
MAKSBM: SETZM BMBUF ;ZERO FIRST WORD IN SAB BUFFER
MOVE T1,[BMBUF,,BMBUF+1] ;CONSTRUCT A BLT POINTER
BLT T1,BMBUF+177 ;ZERO ALL WORDS IN SAB BUFFER
MOVE T1,LSTLBN ;GET HIGHEST LBN# IN VOLUME
IDIVI T1,^D4096 ;COMPUTE T1=# OF BLOCKS NEEDED IN BM
ADDI T1,1 ;ALWAYS NEED AT LEAST 1 BLOCK
STOR. T1,BCNT ;SAVE "SBM-SIZE-IN-BLKS" INTO SAB ITSELF
LOAD. T1,BCNT ;GET # OF SBM BLOCKS
IMULI T1,4 ;TURN INTO AN OFFSET
SUBI T1,4 ;BACK UP ONE SLOT
MOVEM T1,TMPOFF ;SAVE OFFSET FOR STOR. BELOW
MOVE T2,LSTLBN ;GET LAST BLOCK IN VOLUME
STOR. T2,BMXL,TMPOFF ;INSERT LOW PART INTO BM BUF
LSH T2,-^D16 ;DROP LOW WORD, POSITION HIGH
STOR. T2,BMXH,TMPOFF ;INSERT HIGH PART INTO BM BUF
;N.B.: THERE IS SOME ODD CODE IN "INI" IN MODULE "INIBIT" WHICH
;APPARENTLY RESULTS IN PUTTING SOME STUFF IN THE PDP11 WORD IMMEDIATELY
;BEFORE THE PDP11 WORD WHERE BMAX RESIDES. IT'S NOT DUPLICATED HERE CUZ
;I CAN'T FIGURE OUT WHAT IT DOES.
LOAD. T1,BCNT ;GET "SBM-SIZE-IN-BLOCKS"
IMULI T1,^O200 ;COMPUTE T1=OF WORDS IN THE SBM
MOVEM T1,SBMSIZ ;SAVE SIZE OF BM IN PDP10 WORDS
PUSHJ P,GETCOR ;GET MEMORY FOR "INCORE" BM
MOVEM T1,SBMINC ;SAVE POINTER TO THE "INCORE" BM
SETZM (T1) ;ZERO 1ST WORDN BM
HRLS T1 ;CONSTRUCT A BLT POINTER INTO BM
ADDI T1,1 ;...
MOVE T2,SBMSIZ ;GET SIZE OF INCORE BM...
ADDI T2,-2(T1) ;...TO COMPUTE T2=LAST WORD IN BM
BLT T1,(T2) ;SET INCORE BM TO "ALL BLOCKS USED"
SETZM VOLTAL ;SET FREE-TALLY TO 0
MOVE P1,FSTLBN ;SET P1=1ST BLOCK INSIDE FILES11 VOLUME
MAKSB2: MOVE T1,P1 ;SET T1=BLOCK# INSIDE FILES11 VOLUME
PUSHJ P,GIVSBM ;RETURN (MAKE AVAILABLE) A BLOCK
JFCL ;IGNORE IF BLOCK CANNOT BE RETURNED
ADDI P1,1 ;ADVANCE BLOCK NUMBER WITH VOLUME
; AOS VOLTAL ;COUNT A FREE CLUSTER
CAMGE P1,LSTLBN ;SKIP IFF GONE BEYOND END OF VOLUME
JRST MAKSB2 ;BRANCH TO MARK ANOTHER BLOCK FREE
POPJ P, ;RETURN
; ROUTINE TO WRITE INCORE COPIES OF THE BM AND SAB ONTO DISK
WRTSBM: MOVE T1,SBMLBN ;LOAD T1=1ST LBN IN BITMAP.SYS
PUSHJ P,SUSET ;POSITION TO THAT BLOCK
OUT VIO,[IOWD 200,BMBUF ;WRITE THE SAB BLOCK...
0] ;...AS THE FIRST BLOCK IN BITMAP.SYS
SKIPA
ERROR <OUT failed to write SAB buffer>
MOVE T1,SBMSIZ ;LOAD T1=SIZE (IN WORDS) OF INCORE BM
IMUL T1,[-1,,0] ;CONVERT T1=AOBJN TO INCORE BM
HRR T1,SBMINC ;...INSERT ADDRESS INTO AOBJN IN T1
SUBI T1,1 ;CONVERT T1=IOWD POINTER TO INCORE BM
SETZ T2, ;LOAD T2=ENDING IOWD
OUT VIO,T1 ;WRITE BM ONTO DISK
POPJ P, ;RETURN IF I/O WAS GOOD
ERROR <OUT failed to write SBM blocks>
; ROUTINE TO READ IN THE DISK COPY OF THE SBM FILE BITMAP.SYS
REDSBM: MOVE T1,SBMLBN ;LOAD T1=1ST LBN IN BITMAP.SYS
PUSHJ P,SUSET ;POSITION TO THAT BLOCK
IN VIO,[IOWD 200,BMBUF ;READ SAB BLOCK INTO RESERVED BUFFER
0] ;...
SKIPA ;SKIP IF I/O WAS GOOD
ERROR <Can't read SAB block>
LOAD. T1,BCNT ;GET SIZE OF THE BM PORTION
IMULI T1,200 ;COMPUTE T1=#WORDS IN THE BM
MOVEM T1,SBMSIZ ;REMEMBER SIZE OFBM PORTION OF THE SBM
PUSHJ P,GETCOR ;GET MEMORY TO STORE SBM IN
MOVEM T1,SBMINC ;SAVE POINTER TO INCORE COPY OF BM
HRRZ T1,SBMSIZ ;LOAD T1=#WORDS IN THE BM
IMUL T1,[-1,,0] ;CONVERT T1=AOBJN INTO THE BM
HRR T1,SBMINC ;INSERT RH(T1)=POINTER TO THE BM
SUBI T1,1 ;CONVERT T1=IOWD POINTER TO THE BM
SETZ T2, ;LOAD T2=ENDING IOWD
IN VIO,T1 ;READ THE BM INTO CORE
SKIPA ;SKIP IF I/O WAS GOOD
ERROR <Can't read BM blocks in BITMAP.YSS>
SETZM VOLTAL ;START FREE-TALLY AT 0
HRRZ T1,SBMINC ;INITIALIZE A BYTE POINTER TO INCORE BM
HRLI T1,(POINT 1,0) ;...
MOVE T2,SBMSIZ ;INITIALIZE A BIT COUNT TO THE INCORE BM
IMULI T2,^D36 ;...
REDSB2: ILDB T3,T1 ;GET A BIT FROM THE BM
SKIPE T3 ;SKIP IFF BLOCK IS IN USE
AOS VOLTAL ;COUNT A FREE BLOCK IF BLOCK IS FREE
SOJG T2,REDSB2 ;LOOK AT ALL THE BITS IN THE BM
MOVE T2,SBMSIZ ;GET SIZE OF STORAGE MAP IN WORDS
IMULI T2,^D32 ;COMPUTE # OF BLOCKS DESCRIBED (MAX)
SUBI T2,1 ;HIGH BLOCK # IS #BLOCKS-1
CAMGE T2,LSTLBN ;SKIP IFF BOUNDS LOOK REASONABLE
MOVEM T2,LSTLBN ;MIGHT BE RP04 ON RP06 OR USED MAINT CYLS
POPJ P, ;EXIT
; SUBROUTINE TO MARK A BLOCK (T1) AS AVAILABLE IN THE SAT
GIVSBM: PUSHJ P,SAVE4 ;SAVE SOME ACS
MOVE P1,T1 ;COPY BLOCK #
IDIVI P1,^D4096 ;COMPUTE RELATVIE SBM BLOCK #
MOVSI P4,1 ;
CAIGE P1,176 ;SKIP IF BEYONDS BOUNDS OF BMBUF
ADDM P4,BMBUF+1(P1) ;ADJUST SAB COUNT FOR THAT SBM BLOCK
MOVE P1,T1 ;COPY BLOCK # AGAIN
IDIVI P1,^D32 ;COMPUTE WHICH WORD IN THE SBM IT IS
;(WHICH PDP10 WORD THAT IS!)
ADD P1,SBMINC ;ADD IN BASE OF TABLE
MOVE P2,B32TBL(P2) ;CONVERT TO ACTUAL BIT
TDNN P2,@P1 ;BIT ON YET?
AOS VOLTAL ;NO, COUNT A FREE BLOCK
ORM P2,@P1 ;TURN ON THE BIT
POPJ P, ;RETURN
; SUBROUTINE TO MARK A BLOCK (T1) AS USED IN THE SAT
;
; T1/ REAL BLOCK NUMBER
;
TAKSBM: PUSHJ P,SAVE4 ;SAVE SOME ACS
MOVE P1,T1 ;COPY BLOCK #
IDIVI P1,^D4096 ;COMPUTE RELATVIE SBM BLOCK #
CAILE P1,176 ;SKIP IF VALID
JRST TAKSB0 ;BRANCH IF BEYOND BOUNDS OF BMBUF
LDB P4,[POINT 16,BMBUF+1(P1),17]
SKIPE P4 ;DON'T LET IT GO "NEGATIVE"
SUBI P4,1
DPB P4,[POINT 16,BMBUF+1(P1),17]
TAKSB0: MOVE P1,T1 ;COPY BLOCK # AGAIN
IDIVI P1,^D32 ;COMPUTE WHICH WORD IN THE SBM IT IS
;(WHICH PDP10 WORD THAT IS!)
MOVE P2,B32TBL(P2) ;CONVERT TO ACTUAL BIT
ADD P1,SBMINC ;COMPUTE INCORE WORD ADDRESS
TDNE P2,@P1 ;ALREADY OFF?
SOS VOLTAL ;NO, COUNT A FREE BLOCK
ANDCAM P2,@P1 ;TURN OFF THE BIT
POPJ P, ;RETURN
; ROUTINE TO SCAN THE STORAGE-BIT-MAP AND RETURN A CHUNK
;
; T1/ 0 ;TREAT AS IF T1 CONTAINED 1
; T1/ +VE ;RETURN THE SMALLEST CHUNK WHICH HAS (T1) BLOKS
;RETURN:
; T1/ # BLOCKS
; T2/ 1ST BLOCK IN CHUNK
;
; N.B.: THIS ROUTINE MIGHT RETURN MORE THAN 256. BLOCKS IN WHICH CASE
; IT IS THE CALLER'S RESPONSIBILITY TO BREAK THE CHUNK INTO
; PIECES IN ORDER TO FIT INTO FILES-11 RETRIEVAL POINTERS
SCNSBM: PUSHJ P,SAVE4 ;SAVE SOME ACS
outchr ["+"]
CAIG T1,0 ;-VE OR 0 BLOCKS REQUESTED?
MOVEI T1,1 ;YES, JUST ASK FOR ONE
PUSH P,T3 ;SAVE SOME ACS
PUSH P,T4 ;...
MOVEI P1,377777
HRLOM P1,BEST ;SET BEST CHUNK TO WORST POSSIBLE
SETZM BIG ;FORGET PREVIOUS BIGGEST CHUNK
SETZB P1,P2
SETZB P3,P4
MOVE P1,SBMSIZ ;LOAD P1=# WORDS IN INCORE MAP
IMUL P1,[-1,,0] ;CONVERT P1=AOBJN COUNTER
HRR P1,SBMINC ;INSERT P1=POINTER TO INCORE MAP
MOVE P2,FSTLBN ;LOAD P2=BLOK# OF FIRST BLOK IN VOLUME
IDIVI P2,^D32 ;COMPUTE P2=WORD# IN MAP FOR 1ST BLOK
HRLS P2 ;CONVERT P2=WORD#,,WORD#
ADD P1,P2 ;MAKE P1=POINTER TO 1ST (VALID) WORD
SCNSB0: SKIPN T3,(P1) ;SKIP IFF AT LEAST 1 FREE BLOCK
AOBJN P1,SCNSB0 ;LOOP LOOKING FOR FREE BLOCKS
JUMPGE P1,SCNSB8 ;BRANCH IF OUT OF BITS TO LOOK AT
MOVSI P2,-^D32 ;START AT BIT#0
SCNSB1: TDNN T3,B32TBL(P2) ;SKIP IF WE FOUND THE FIRST BIT INA RUN
AOBJN P2,SCNSB1 ;LOOP TILL WE FIND THE FREE BIT
SCNSB2: DMOVE P3,P1 ;COPY P3=1ST WORD, P4=1ST BIT
SETZ T4, ;ZERO COUNT OF CONSECUTIVE BIT
SCNSB3: TDZN T3,B32TBL(P2) ;SKIP IF WE HAVE A FREE BLOCK
JRST SCNSB6 ;BRANCH IF WE FIND THE END OF RUN
ADDI T4,1 ;COUNT THE BLOK
AOBJN P2,SCNSB3 ;LOOP TO FIND NEXT BIT
AOBJN P1,[MOVE T3,(P1) ;LOAD NEXT WORD OF BITS
MOVSI P2,-^D32 ;START BIT#0
JRST SCNSB3] ;AND CONTINUE COUNTING BITS
; HERE IF WE RUN OUT OF BITS TO SCAN
;HERE WHEN WE REACH THE END OF A RUN
SCNSB6: CAMLE T4,BIG ;SKIP IF NOT ABSOLUTE BIGGEST CHUNK SEEN
PUSHJ P,[MOVEM T4,BIG ;...REMEMBER SIZE OF ABSOLUTE BIGGEST
DMOVEM P3,BIGP1 ;...REMEMBER ADDRESS OF ABSOLUTE BIGST
POPJ P,0] ;...
CAMGE T4,T1 ;BIG ENOUGH TO CONSIDER?
JRST SCNSB7 ;GO TO NEXT REGION
CAML T4,BEST ;YES, IS IT SMALLER THAN BEST SO FAR?
JRST SCNSB7 ;NO, GO ON TO NEXT FREE REGION
MOVEM T4,BEST ;YES, REMEMBER IT'S SIZE
DMOVEM P3,BESTP1 ;YES, REMEMBER IT'S LOCATION
SCNSB7: AOBJN P2,SCNSB2 ;IF MORE BITS THIS PDP11 WORD, CONTINUE
AOBJN P1,SCNSB0 ;ELSE RESTARTT HE SEARCH
SCNSB8: MOVE T1,BEST ;GET BEST SIZE FOUND
CAMN T1,[377777,,777777] ;CHECK FOR FAILURE
JRST SCNSB9 ;
HRRZ T2,BESTP1 ;LOAD T2=BEST 32WORD BLOCK
SUB T2,SBMINC ;COMPUTE T2=OFFSET
IMULI T2,^D32 ;
HRRZ T3,BESTP2
ADD T2,T3
POP P,T4
POP P,T3
JUMPE T1,SCNS11 ;OH DARN, SOME SORT OF BUG
OUTCHR ["-"]
JRST CPOPJ1 ;GIVE GOOD RETURN
SCNSB9: MOVE T1,BIG ;GET BIGGEST
JUMPE T1,SCNS10 ;GIVE UP, TOTAL FAILURE, NO BLOCKS
HRRZ T2,BIGP1 ;GET P1 OF BIGGEST CHUNK
SUB T2,SBMINC ;COMPUTE T2=OFFSET
IMULI T2,^D32
HRRZ T3,BIGP2
ADD T2,T3
POP P,T4
POP P,T3
outchr ["-"]
JUMPE T1,SCNS11 ;OH DARN, SOME SORT OF IMPOSSIBLE BUG
JRST CPOPJ1 ;GIVE GOOD RETURN
SCNS10: POP P,T4 ;RESTORE T4
POP P,T3 ;RESTORE T3
POPJ P, ;GIVE ERROR RETURN
SCNS11: TYPE <?? SCNSBM RETURNED 0 BLOCKS
>
POPJ P,
; ROUTINE TO "TYPE" OUT THE STORAGE BIT MAP
TYPSBM: MOVE P1,SBMSIZ ;GET SIZE OF SBM IN WORDS
IMULI P1,^D32 ;GET SIZE OF SBM IN BITS
SETZ P2, ;START AT BLOCK 0
MOVEI P4,0 ;P4=PROTOTYPE=NOT FREE
TYPSB1: SETZ P3, ;ZERO COUNT OF BLOCK IN REGION
TYPSB2: SOJL P1,TYPSB3 ;BRANCH IF OUT OF BITS
MOVE T1,P2 ;COPY BLOCK NUMBER
IDIVI T1,^D32 ;COMPUTE WORD,BIT #S
ADD T1,SBMINC ;COMPUTE WORD-ADDRESS
MOVE T2,B32TBL(T2) ;COMPUTE BIT MASK
TDNN T2,@T1 ;SKIP IF BIT IS FREE
TDZA T1,T1
MOVEI T1,1 ;BIT IS FREE
CAMN T1,P4 ;SAME AS CURRENT REGION?
AOJA P3,[AOJA P2,TYPSB2] ;YES, COUNT BLOCK, ADVANCE AND LOOP
TYPSB3: MOVE T1,P3 ;GET BLOCK COUNT
PUSHJ P,DECOUT ;TYPE IT
TYPE < blocks >
SKIPE P4 ;SKIP IF NOT FREE
TYPE <free >
SKIPN P4
TYPE <used >
MOVE T1,P2 ;GET HIGH BLOCK NUMBER
SUB T1,P3 ;COMPUTE LOW BLOCK
PUSHJ P,OCTOUT ;TYPE LOW BLOCK
TYPE < to > ;
MOVE T1,P2 ;
SUBI T1,1
PUSHJ P,OCTOUT ;TYPE HIGH BLOCK
PUSHJ P,CRLF
TRC P4,1 ;REVERSE LOGIC FOR SCAN
JUMPGE P1,[AOJA P1,TYPSB1] ;LOOP IF MORE TO SCAN
POPJ P, ;ELSE DONE
SUBTTL WILD CARD ROUTINES
; ROUTINE TO INITIALIZE THE WILD CARD RSX20F FDB ROUTINE
RLDINI: SETZM WDICNT ;#RECORDS IN THE CURRENT DIRECTORY BLOK
SETOM WDIBNO ;RELATIVE BLOK# OF CURRENT D'RECTRY BLOK
SETZM MASCNT ;#RECORDS LEFT IN CURRENT MFD BLOK
SETOM MASBNO ;RELATIVE BLOK# OF CURRENT MFD BLOK
SETZM DIRCNT ;# OF DIRECTORY FILES FOUND ON VOLUME
SETZM DIRMAT ;# OF DIRECTORY FILES FOUND TO MATCH
SETZM FILCNT ;# OF FILES FOUND ON VOLUME
SETZM FILMAT ;# OF FILES FOUND TO MATCH
POPJ P, ;ALL INIT'ED
; ROUTINE TO TAKE 1 RIGHT JUSTIFIED PDP11 WORD OF .RAD50 FORMAT
; AND CONVERT TO 1 RIGHT JUSTIFIED PDP10 WORD OF SIXBIT
C5T6: IDIVI T1,50*50 ;GET 1ST RAD50 LETTER IN T1
IDIVI T2,50 ;GET 2ND IN T2, 3RD IN T3
MOVE T1,R2STBL(T1) ;CONVERT TO SIXBIT
MOVE T2,R2STBL(T2) ;CONVERT TO SIXBIT
MOVE T3,R2STBL(T3) ;CONVERT TO SIXBIT
LSH T1,^D12 ;MAKE 1ST LETTER HIGHEST ORDER
LSH T2,^D6 ;MAKE 2ND LETTER MIDDLE ORDER
IOR T1,T2 ;MERGE HIGH AND MIDDLE ORDER
IOR T1,T3 ;MERGE THOSE WITH LOW ORDER
POPJ P,
; ROUTINE TO TAKE 1 RIGHT JUSTIFIED PDP10 WORD OF SIXBIT
; AND CONVERT IT TO 1 RIGHT JUSTIFIED PDP11 WORD OF .RAD50
C6T5: IDIVI T1,100*100 ;GET 1ST 6BIT CHAR IN T1, 2ND&3RD IN T2
IDIVI T2,100 ;GET 2ND IN T2, 3RD IN T3
MOVE T1,S2RTBL(T1) ;CONVERT TO RAD50
MOVE T2,S2RTBL(T2) ;...
MOVE T3,S2RTBL(T3) ;...
IMULI T1,50
ADDI T1,(T2)
IMULI T1,50
ADDI T1,(T3)
POPJ P,
; ROUTINE TO RETURN CONSECUTIVE MATCHING FILE BLOCKS
;
;ENTER:
; T1/ FDB WE'RE TRYING TO MATCH
; T2/ FDB TO EXPAND MATCHING SPEC INTO
NXTFDB: PUSHJ P,SAVE4 ;GET SOME ACS
DMOVE P1,T1 ;COPY THE ARGUMENT ACS
SETOM .FXNMM(P2)
SETOM .F2NMM(P2)
SETOM .FXEXT(P2)
NXTFD1: SOSGE WDICNT ;SKIP IF MORE FILE RECORDS
JRST NXTDBK ;NO MORE IN THIS BLOCK OF DIRECTORY
LOAD. T1,UFN1,WDIOFF ;READ FROM THE DIRECTORY BUFFER
PUSHJ P,C5T6 ;CONVERT RAD50 FILENAME PART 1 TO SIXBIT
HRLZM T1,.FXNAM(P2) ;STASH INTO OUTPUT FDB TEMPORARILY
LOAD. T1,UFN2,WDIOFF ;GET 2RD 3RD OF FILE NAME FROM DIR BUF
PUSHJ P,C5T6 ;CONVERT RAD50 FILENAME PART 2 TO SIXBIT
HRRM T1,.FXNAM(P2) ;STASH INTO OUTPUT FDB TEMPORARILY
LOAD. T1,UFN3,WDIOFF ;GET 3RD 3RD OF FILE NAME FROM DIRBUF
PUSHJ P,C5T6 ;CONVERT 3RD 3RD TO SIXBIT
HRLZM T1,.F2NAM(P2) ;STASH THAT TOO
LOAD. T1,UFTY,WDIOFF ;GET FILE TYPE FROM DIRECTORY BUFFER
PUSHJ P,C5T6 ;CONVERT TO SIXBIT
HRLZM T1,.FXEXT(P2) ;STASH INTO OUTPUT FDB TEMPORARILY
SKIPE .FXEXT(P2) ;SKIP IF FILE TYPE IS NULL
JRST NOTNUL ;BRANCH IF FILE TYPE *NOT* NULL
SKIPN .FXNAM(P2) ;SKIP IF NOT NULL FILE NAME
SKIPE .F2NAM(P2) ;SKIP IF FILE IS COMPLETELY NULL
SKIPA
JRST [SKIPN .FXDEV(P1) ;SKIP IF NOT LOOKING FOR NULL
SKIPE .FXNAM(P1) ;SKIP IF WE WERE LOOKING FOR NULL SLOT
JRST NULREC ;FORGET IT IF WE WERE'NT
JRST NULGOT] ;GIVE IT
NOTNUL: LOAD. T1,UFNO,WDIOFF ;GET FILE NUMBER
JUMPE T1,NULREC ;IGNORE THIS FHB IF FILE NUMBER IS ZERO
AOS FILCNT ;COUNT A FOUND FILE
MOVE T1,.FXNAM(P2) ;GET FILE NAME IN DIRECTORY
AND T1,.FXNMM(P1) ;TURN OFF WILD CHARACTERS
MOVE T2,.FXNAM(P1) ;GET FILE NAME IN REQUEST
AND T2,.FXNMM(P1) ;TURN OFF IT'S WILD CAHRACTERS TOO
CAME T1,T2 ;SKIP IF THEY MATCH
JRST NULREC ;NO, SKIP REMAINDER
MOVE T1,.F2NAM(P2) ;GET 2ND HALF OF FILE NAME
AND T1,.F2NMM(P1) ;TURN OFF WILD CHARACTERS
MOVE T2,.F2NAM(P1) ;GET 2ND PART OF REQ'D NAME
AND T2,.F2NMM(P1) ;TURN OF WILD CHARACTERS IN IT TOO
CAME T1,T2
JRST NULREC ;GIVE UP IF NO MATCH THERE
LOAD. T1,UFTY,WDIOFF ;GET FILE TYPE FROM DIRTORY BUFFER
PUSHJ P,C5T6 ;CONVERT TO SIXBIT
HRLZM T1,.FXEXT(P2) ;STASH INTO OUTPUT FDB TEMPORARILY
AND T1,.FXEXT(P1) ;ISOLATE THE NON-WILD CHARACTERS
HLRZ T2,.FXEXT(P1) ;GET FILE TYPE
AND T2,.FXEXT(P1) ;TURN OFF WILD BYTES
CAME T1,T2
JRSt NULREC
LOAD. T1,UVER,WDIOFF ;GET GENERATION NUMBER FROM UFD ENTRY
SKIPE .FXGEN(P1) ;DID THEY GIVE A GENERATION TO MATCH?
CAMN T1,.FXGEN(P1) ;YES, DOES THIS MATCH?
AOSA FILMAT ;COUNT A MATCHING FILE
JRST NULREC ;NO, NO MATCH SO IGNORE THIS FILE
NULGOT: LOAD. T1,UFNO,WDIOFF ;GET FILE NUMBER
MOVEM T1,.FXNUM(P2) ;STORE FILE NUMBER
LOAD. T1,UVER,WDIOFF ;GET FILE GENERATION #
MOVEM T1,.FXGEN(P2) ;SAVE GENERATION #
LOAD. T1,UFSQ,WDIOFF ;GET FILE SEQUENCE
MOVEM T1,.FXSEQ(P2) ;STORE SEQ #
LOAD. T1,UFRV,WDIOFF ;GET RELATIVE VOLUME
MOVEM T1,.FXRVN(P2) ;STORE RELATIVE VOLUME NUMBER
MOVEI T1,.DIROFF ;GET OFFSET FOR A DIRECTORY RECORD
ADDM T1,WDIOFF ;STEP TO NEXT RECORD NEXT PASS
DMOVE T1,P1 ;RESTORE THE ACS
JRST CPOPJ1 ;GIVE GOOD RETURN
NULREC: MOVEI T1,.DIROFF ;GET OFFSET FOR A DIRECTORY RECORD
ADDM T1,WDIOFF ;ADVANCE TO NEXT RECORD
JRST NXTFD1 ;LOOP TO LOOK AT NEXT RECORD
;HERE IF A DIRECTORY RUNS OUT OF RECORDS IN A BLOCK
NXTDBK: SKIPGE WDIBNO ;SKIP IF WDIBNO IS VALID
JRST NXTDIR ;NO, GO TO NEXT ONE
MOVE T2,WDIBNO ;GET RELATIVE BLOCK # OF NEXT BLOCK
AOS WDIBNO ;STEP TO NEXT BLOCK NEXT TIME
MOVEI T1,WDIFHB ;LOOK AT DIRECTORY'S FHB
PUSHJ P,SCNRET ;FIND THAT BLOCK #
JRST NXTDIR ;GO ON TO NEXT DIRECTORY
MOVEM T1,WDIPBN ;REMEMBER PHYSICAL BLOCK #
PUSHJ P,SUSET ;POSITION DISK TO READ THAT NEXT
IN VIO,[IOWD 200,WDIBUF
0] ;READ INTO DIRECTORY BUFFER
SKIPA
ERROR <I/O error reading directory file>
MOVEI T1,<WDIBUF-MFDDAT>*4 ;MAKE Uxxx POINT AT WDIBUF
MOVEM T1,WDIOFF ;MAKE LOAD./STOR. WORK
MOVEI T1,WDIFHB
MOVE T2,WDIBNO
SUBI T2,1
PUSHJ P,EOFBYT
IDIVI T1,.DIROFF ;COMPUTE T1=# RECORDS THIS BLOCK
MOVEM T1,WDICNT ;INITIALIZE COUNT FOR THIS BLOCK
JRST NXTFD1 ;LOOP TO READ THIS BLOCK
;HERE IF WE EXHAUST A DIRECTORY, STEP TO THE NEXT RECORD IN THE MFD
NXTDIR: SOSGE MASCNT ;SKIP IF MORE MFD RECORDS IN THIS BLOK
JRST NXTMBK ;NO MORE, READ NEXT MFD BLOCK
LOAD. T1,UFTY,MASOFF ;GET FILE TYPE OF NEXT RECORD
TSC T1,[.RAD50 <DIR>] ;COMPARE TO "DIR"
JUMPN T1,NXTDI2 ;BRANCH IF NOT A DIR FILE
LOAD. T1,UFN1,MASOFF ;GET NAME OF IT
PUSHJ P,C5T6 ;GET SIXBIT
HRLZM T1,UFDNAM ;SAVE IT
LOAD. T1,UFN2,MASOFF ;GET RH OF FILE NAME
PUSHJ P,C5T6 ;GET SIXBIT OF IT
HRRM T1,UFDNAM ;REMEMBER IT
LOAD. T1,UFN3,MASOFF ;GET 3RD "HALF" OF FILE NAME
PUSHJ P,C5T6 ;CONVERT TO SIXBIT
HRLZM T1,UF2NAM ;REMEMBER LAST PART OF FILE NAME
AOS DIRCNT
MOVE T1,.FXDIN(P1) ;GET DIRECTORY NAME
AND T1,.FXDNM(P1) ;MASK BY CORRECT MASK
MOVE T2,UFDNAM ;GET NAME WE JUST SAW
AND T2,.FXDNM(P1) ;MASK IT TOO
CAME T1,T2
JRST NXTDI2
MOVE T1,.F2DIN(P1) ;GET 2ND HALF OF DIRECTORY NAME
AND T1,.F2DNM(P1) ;MASK 2ND HALF AS WELL
MOVE T2,UF2NAM ;GET 2ND HALF OF ONE WE JUST SAW
AND T2,.F2DNM(P1) ;MASK IT TOO
HRR T1,T2 ;ENSURE RHS MATCH
CAME T1,T2 ;SKIP IF FILE REALLY MATCHES
JRST NXTDI2 ;BRANCH TO CONSIDER NEXT DIRECTORY
LOAD. T1,UFNO,MASOFF ;GET FILE NUMBER OF IT
JUMPE T1,NXTDI2 ;SKIP THIS ENTRY IF FILE#=0
AOS DIRMAT ;COUNT A MATCHING DIRECTORY
MOVEI T2,WDIFHB ;GET DIRECTORY FHB BUFFER
PUSHJ P,REDFHB ;READ THAT DIRECTORY
MOVEI T1,.DIROFF
ADDM T1,MASOFF ;STEP TO NEXT RECORD NEXT TIME
SETZM WDIBNO ;START WITH BLOCK 0
SETZM WDICNT ;START WITH NO RECORDS
JRST NXTFD1 ;GO DO IT
NXTDI2: MOVEI T1,.DIROFF ;
ADDM T1,MASOFF ;STEP TO NEXT RECORD NEXT TIME
JRST NXTDIR ;READ NEXT RECORD IN MFD
;HERE IF WE EXHAUST A SET OF MFD RECORDS, READ NEXT MFD BLOCK
NXTMBK: MOVEI T1,BUF444 ;LOOK AT MFD'S FHB
AOS T2,MASBNO ;GET MFD BLOK #
PUSHJ P,SCNRET ;SCAN IT
JRST EOFMFD
PUSHJ P,SUSET ;POSITION DISK
IN VIO,[IOWD 200,MASBUF ;
0]
SKIPA
ERROR <I/O error reading MFD>
MOVEI T1,BUF444
MOVE T2,MASBNO
PUSHJ P,EOFBYT
IDIVI T1,.DIROFF
MOVEM T1,MASCNT ;PLENTY NOW
MOVEI T1,<MASBUF-MFDDAT>*4
MOVEM T1,MASOFF
JRST NXTDIR
EOFMFD: SKIPE DIRCNT ;ANY DIRECTORIES SEEN AT ALL?
POPJ P, ;YES, DON'T MENTION FAILURE
TYPE <% No directory files found
>
POPJ P,
MAK2D: IDIVI T1,^D10 ;DIVIDE INTO 2 PARTS
LSH T2,^D8 ;MAKE ROOM
IORI T1,<"0"_^D8>+"0"(T2);TURN INTO PDP10 ASCII
MOVSI T1,(T1) ;CONVERT TO PDP11 FORMAT
POPJ P,0
MAKSD: IDIVI T1,^D10 ;DIVIDE INTO 2 PARTS
LSH T2,^D8 ;MAKE ROOM
JUMPE T1,MAK1D
IORI T1,<"0"_^D8>+"0"(T2);TURN INTO PDP11 ASCII
MOVSI T1,(T1)
POPJ P,0
MAK1D: IORI T1,<"0"_^D8>+" "(T2);TURN INTO PDP11 ASCII
MOVSI T1,(T1)
POPJ P,0
IMPURE: GETPPN T1,
JFCL
MOVEM T1,MYPPN
SETZM LOWZRO
SETZM NULFDB+.FXNAM ;NULL NAME
SETOM NULFDB+.FXNMM ;EXPLICITLY
SETZM NULFDB+.F2NAM ;...
SETOm NULFDB+.F2NMM ;...
SETZM NULFDB+.FXEXT ;
HLLOS NULFDB+.FXEXT ;...
SETZM NULFDB+.FXGEN ;...
SETOM NULFDB+.FXDNM ;DIRECTORY IS EXACTLY SPECIFIED
SETOM NULFDB+.F2DNM ;...
SETZM DEFFDB+.FXDEV
SETZM DEFFDB+.FXDIR
SETZM DEFFDB+.FXLNK
SETZM DEFFDB+.FXSWT
SETZM DEFFDB+.FXMOD
POPJ P,0
; ROUTINE TO FIND IMPLIED FLAGS FOR RAD50 EXTENSION IN T1
;ENTER: T1/ RIGHT JUSTIFIED RAD50 FILE TYPE WORD
;EXIT: T1/ IMPLIED FLAGS OR 0
EXTCHK: PUSHJ P,SAVE4 ;SAVE SOME ACS
PUSHJ P,C5T6 ;CONVERT RAD50 TO SIXBIT
MOVE P1,T1 ;COPY FILE TYPE TO SAFER AC
SETZ T1, ;T1=FLAGS WHICH THIS ROUTINES WANTS SET
MOVE P2,[POINT 36,IMGTBL,35] ;P2=POINTER INTO /IMAGE LIST
EXTCH1: ILDB P3,P2 ;GET NEXT POSSIBLE EXT
JUMPE P3,EXTCH2 ;NO MOR LEFT
CAME P3,P1 ;SKIP IF THIS TYPE IMPLIES /IMAGE
JRST EXTCH1 ;BRANCH IF THIS TYPE DON'T IMPLY /IMAGE
TDO T1,[S$IMAG] ;IMPLY /IMAGE
EXTCH2: MOVE P2,[POINT 36,CTGTBL,35] ;P2=POINTER TO /CONTIG TABLE
EXTCH3: ILDB P3,P2 ;GET P3=NEXT FILE TYPE
JUMPE P3,EXTCH4 ;BRANCH IF END OF /CONTIG TABLE
CAME P3,P1 ;SKIP IFF THIS FILE TYPE IMPLIES /CONTIG
JRST EXTCH3 ;BRANCH IF FILE TYPE DON'T IMPLY /CONTIG
TDO T1,[S$CONT] ;IMPLY /CONTIG
EXTCH4: POPJ P,
DEFINE XT(.LIST),<IRP .LIST,<''.LIST''>>
IMGTBL: XT <ABS,BIN,BIC,CFG,CIL,DIR,EXB,LBO,LDA,LDR,LOD,MCB,MFD,OBJ,OLB,SAV,SML,SYM,SYS,TSK,UFD>
0
CTGTBL: XT <SML,OLB,TSK,SYS,DIR>
0
; SUBROUTINE TO CHECKSUM A BLOCK OF PDP11 MEMORY
CHKSUM: PUSHJ P,SAVE4 ;SAVE SOME ACS
SETZ P1, ;ZERO IT
MOVE P2,[POINT 18,(T1)]
CHKSU1: ILDB P3,P2 ;GET A WORD
ADDI P1,(P3) ;COMPUTE CHECKSUM
SOJG T2,CHKSU1 ;LOOP TILL DONE
HRRZ T1,P1 ;RETURN IT IN T1
ANDI T1,177777 ;TURN OFF CARRY BITS
POPJ P,0
; ROUTINE TO OPEN A FILES-11 VOLUME
OPNVOL: PUSHJ P,OPNVIO ;OPEN THE DISK FOR I/O
PUSHJ P,G11HOM ;GET THE FILES-11 HOME BLOCK
ERROR <Cannot open FILES-11 volume for I/O>
SETZM BUF111 ;MAKE SURE WE KNOW INDEXF NOT IN CORE
LOAD. T2,IBLL ;GET DISK ADDRESS OF IBM LOW WORD
LOAD. T1,IBLH ;GET HIGH WORD
LSH T1,^D16 ;POSITION HIGH PART
OR T1,T2 ;COMPUTE T1=DISK ADDRESS OF IBM
MOVEM T1,IBMLBN ;SAVE ADDRESS OF IBM
LOAD. T2,IBSZ ;GET SIZE OF IBM IN BLOCKS
ADD T1,T2 ;COMPUTE
MOVEM T1,FHBLBN ;SAVE ADDRESS OF KNOWN FHBS
LOAD. T2,IBSZ ;GET SIZE OF IBM IN BLOCKS
IMULI T2,200 ;COMPUTE # OF PDP10 WORDS
MOVEM T2,IBMSIZ ;SAVE SIZE
PUSHJ P,REDIBM ;READ THE IBM
MOVEI T1,2 ;FILE#2=BITMAP.SYS
MOVEI T2,FHBBUF ;USE THE NORMAL BUFFER
PUSHJ P,REDFHB ;READ THAT FHB INTO FHBBUF
LOAD. T2,RLBN ;GET LOW LBN OF BITMAP (IE: SAB)
LOAD. T1,HRET ;GET HIGH LBN OF BITMAP
LSH T1,^D16 ;MAKE ROOM FOR LOW
OR T1,T2 ;COMPUTE T1=DISK ADDRESS OF SAB BLOK
MOVEM T1,SBMLBN ;SAVE SBM LBN
PUSHJ P,REDSBM ;READ IT
MOVEI T1,1 ;FILE#1=INDEXF.SYS
MOVEI T2,BUF111 ;READ INDEXF.SYS FHB INTO BUF111
PUSHJ P,REDFHB ;READ IN FHB FOR INDEXF
MOVEI T1,4 ;FILE#4=000000.DIR
MOVEI T2,BUF444 ;READ 000000.DIR FHB INTO BUF444
PUSHJ P,REDFHB ;READ IN FHB FOR 000000.DIR
POPJ P, ;RETURN
; ROUTINE TO FIND AND LOAD THE FILES-11 HOME BLOCK
G11HOM: PUSHJ P,SAVE2 ;SAVE P1
SKIPE FAKVOL
JRST L11HOM ;GO GET LOGICAL INFO
PUSHJ P,G10HOM ;GET THE PDP10 HOME BLOCKS
MOVE T1,HOME1+HOMNAM ;
MOVE T2,HOME2+HOMNAM ;GET HOMNAM FROM BOTH
CAME T1,[SIXBIT .HOM.] ;DUE TO AN ERROR IN ONE?
CAMN T1,[SIXBIT .HOM.] ;...?
JRST G11HO3 ;BRANCH IF WE EXPECT TOPS10 HOME BLOCK
MOVEI P1,1 ;CURRENT BLOCK #
SETZM FSTLBN ;FIRST LBN IN VOLUME
MOVE T1,DSKBLK+.DCUSZ ;GET HIGH LBN
SUBI T1,1 ;...
MOVEM T1,LSTLBN ;SAVE IT
TYPE <[No PDP10 HOM blocks, scanning for FILES-11 home block]
>
G11HO1: MOVE T1,P1 ;
PUSHJ P,SUSET ;POSITION DISK
IN VIO,[IOWD 200,H11BUF ;READ HOME BLOCK INTO BUFFER
0] ;...
SKIPA T1,H11BUF+HOMNAM ;GET TOPS-10 HOME NAME
TYPE <? I/O error reading FILES-11 home block>,CPOPJ
JUMPL T1,G11HO2 ;SKIP IF TOPS10 HOME BLOCK
MOVE T1,TMP166
;$$ CAME T1,H11BUF+166
;$$ JRST G11HO2 ;NOT HOME
LOAD. T1,IBSZ ;GET INDEX BIT MAP SIZE
JUMPE T1,G11HO2 ;FORGET IT IF ZEROES
LOAD. T1,SBCL ;GET CLUSTER SIZE
CAIE T1,1 ;SKIP IF ONLY SUPPORTED SIZE=1
JRST G11HO2 ;FORGET IT IF STRANGE CLUSTER SIZE
MOVEI T1,H11BUF ;POINT AT HOME BLOCK
MOVEI T2,O.CHK1/2 ;# WORDS TO CHECKSUM
PUSHJ P,CHKSUM ;COMPUTE CHECKSUM
LOAD. T2,CHK1 ;GET CHECKSUM RECORDED IN HOME BLOCK
CAME T1,T2 ;SKIP IF THEY MATCH
JRST G11HO2 ;NOT HOME BLOCK, TRY NEXT 400 MULTIPLE
MOVEI T1,H11BUF ;POINT AT HOME BLOCK
MOVEI T2,o.CHK2/2 ;# WORDS TO CHECKSUM
PUSHJ P,CHKSUM ;COMPUTE CHECKSUM
LOAD. T2,CHK2 ;GET CHECKSUM RECORDED IN HOME BLOCK
MOVEM P1,H11LBN ;REMEMBER HOME BLOCK LBN
CAMN T1,T2 ;SKIP IF THEY MATCH
JRSt G11HO4 ;GO DO MORE IF NEEDED
G11HO2: SKIPE FAKVOL
AOJA P1,.+3
TRZ P1,377 ;TURN OFF POSSIBLE GARBAGE BITS
ADDI P1,400 ;STEP TO NEXT MULTIPLE
CAMG P1,LSTLBN ;TOO FAR?
JRST G11HO1 ;LOOP AGAIN
TYPE <[No FILES-11 home block in bounds of volume]
>
POPJ P,
G11HO3: DMOVE T1,HOME1+HOMFE0 ;GET ADDRESS+VALID BIT
TLZN T1,100000 ;IS IT VALID?
TYPE <[TOPS-10 HOM block denies a FILES-11 volume]
>,CPOPJ
HRRZM T1,1(P) ;SAVE RH OF 18/18 FORMAT
HLLZS T1 ;ISOLATE HIGH BITS
LSH T1,-2
OR T1,1(P) ;INSERT LOW ORDER BITS
MOVEM T1,FSTLBN ;STORE 1ST BLOCK # IN VOLUME
HRRZM T2,1(P) ;SAVE LENGTH
HLLZS T2
LSH T2,-2
OR T2,1(P)
ADD T1,T2 ;ADD IN LENGTH
SUBI T1,1 ;AND -1 TO COMPUTE LAST BLOCK #
MOVEM T1,LSTLBN ;SAVE THAT TO
MOVE P1,FSTLBN ;GET 1ST LBN
JRST G11HO2 ;FIND HOME BLOCK
L11HOM: SETZM FSTLBN
USETI VIO,0 ;PREPARE TO READ RIB
IN VIO,[IOWD 200,LERBLK ;INTO THE LOOKUP BLOCK
0] ;
SKIPA
ERROR <Can't read rib of logical volume file>
SETZM FAKOFS
MOVE T1,LERBLK+.RBALC
MOVEM T1,LSTLBN
MOVEI P1,0
JRST G11HO1
G11HO4: AOS (P) ;ALL OK, SETUP FOR SKIP RETURN
SKIPN T1,FAKVOL
POPJ P, ;ALL DONE
MOVE T1,VOLPTR(T1) ;GET "FP" FOR THIS VOLUME
MOVE T1,.FXSWT(T1) ;GET /SWITCHES FOR THIS VOLUME
TDNE T1,[S$IMAGE] ;SKIP IF NOT IMAGE MODE
POPJ P, ;FAKOFS=0 IF IMAGE MODE
LOAD. T2,IBLL
LOAD. T1,IBLH
LSH T1,^D16
OR T1,T2
TRZ T1,377 ;NOW T1 HAS THE BLOK# THAT HOME BLOK IS
MOVNS T1 ;MAKE IT AN OFFSET
ADD T1,H11LBN
MOVEM T1,FAKOFS
POPJ P,
; SUBROUTINE TO OPEN UP THE FILES-11 VOLUME
OPNVIO: PUSHJ P,SETVOL ;GO APPROVE VOLUME AND RETURN IT IN T1
SKIPE T1,FAKVOL
JRST OPNVIL
MOVE T2,T1 ;PUT IT WHERE WE wANT IT
MOVE T1,[UU.PHS!.IODMP]
MOVE T2,FEUNIT
SETZ T3,
OPEN VIO,T1
ERROR <Can't OPEN FILES-11 volume for I/O>
PUSHJ P,SETCPT ;GO SET COMPATIBILE MODE
POPJ P,0
OPNVIL: MOVE T1,VOLPTR(T1)
MOVEI T2,OPNBLK
MOVEI T3,LERBLK
MOVEI T4,PTHBLK
PUSHJ P,.STOPB##
JFCL
MOVEI T1,17
MOVEM T1,OPNBLK
MOVEI T1,.RBEXT
MOVEM T1,LERBLK
SETZM OPNBLK+.OPBUF ;CLEAR OLD BUFFER ADDRESS WORD
OPEN VIO,OPNBLK
ERROR <Can't OPEN FILES-11 volume for I/O>
MOVE T1,OPNBLK+1
MOVEM T1,FEUNIT
LOOKUP VIO,LERBLK
ERROR <Can't LOOKUP volume for I/O>
HLLZS LERBLK+.RBEXT
ENTER VIO,LERBLK
TYPE <% Can't ENTER volume for writing
>
POPJ P,
; SUBROUTINE TO ESTABLISH 16/18 BIT MODE FOR A PHYSICAL VOLUME
SETCPT: SETZM MOD16 ;CLEAR 16BIT MODE
PUSHJ P,READ10 ;GO READ 10 BLOCKS IN 18BIT
JRST SETCP1 ;FAILED, GO TRY 16 BIT
POPJ P,
SETCP1: MOVE T1,[XWD .DUSEM,T2]
MOVEI T2,VIO
DISK. T1, ;SET UNIT INTO 16 BIT MODE
ERROR <Can't set 16 bit format capatibility>
PUSHJ P,READ10 ;GO READ 10 BLOCKS IN 16BIT
ERROR <Can't determine recorded sector format>
SETOM MOD16 ;SET 16BIT MODE
MOVE T1,DSKBLK+.DCBUC ;GET NUMBER OF BLOCKS IN 16BIT FORMAT
MOVEM T1,DSKBLK+.DCUSZ ;SAVE IN "REGULAR" BLOCKS PER UNIT
POPJ P,
;ROUTINE TO READ THE FIRST TEN BLOCKS ON THE VOLUME
;USED TO SEE IF WE HAVE THE FORMAT CORRECT
READ10: PUSHJ P,SAVE1
MOVSI P1,-^D10
READ11: MOVEI T1,(P1)
PUSHJ P,SUSET
SETSTS VIO,17 ;ENSURE NO ERROR BITS ARE UP
IN VIO,[IOWD 200,TMPBUF] ;DO 1 WORD TRANSFER
JRST READ12 ;GOT ONE RIGHT, KEEP GOING
STATZ VIO,IO.DTE ;SKIP IF NOT FORMAT/HCE ERROR
STATO VIO,IO.DER ;SKIP IF FORMAT/HCE ERROR
JRST READ12 ;GOT AN ERROR, BUT NOT FORMAT ERROR
POPJ P, ;RETURN NOW WITH FORMAT ERROR
READ12: AOBJN P1,READ11
JRST CPOPJ1
; ROUTINE TO TAKE USER'S VOLUME NAME AND SPIFF IF UP
SETVOL: MOVE T1,.FXDEV(FP) ;GET VOLUME NAME
CAIN T1,0 ;IF NO VOLUME NAME
MOVE T1,DEFFDB+.FXDEV ;...TRY FOR DEFAULT INSTEAD
MOVEM T1,DSKBLK+.DCNAM ;SAVE THE USER'S NAME
SETZM FAKVOL
MOVE T1,DSKBLK+.DCNAM
MOVSI T2,-VOLMAX
CAME T1,VOLTBL(T2)
AOBJN T2,.-1
JUMPLE T2,SETVO5
MOVE T1,[XWD 200,DSKBLK] ;
DSKCHR T1, ;
ILLVOL: ERROR <Illegal volume name> ;COMPLAIN
LDB T1,[POINT 3,T1,17] ;GET UNIT TYPE
CAIE T1,.DCTUF ;DSKB0?
CAIN T1,.DCTPU ;OR RPA0?
JRST SETVO2 ;YES, THATS OK
CAIE T1,.DCTFS ;DSKB?
JRST ILLVOL ;NO, TOO VAGUE
SETVO2: MOVE T1,DSKBLK+.DCNAM
CAMN T1,DSKBLK+.DCUPN
JRST SETVO3
TYPE <[>
MOVE T1,DSKBLK+.DCNAM
PUSHJ P,SIXOUT
TYPE < will be treated as >
MOVE T1,DSKBLK+.DCUPN
PUSHJ P,SIXOUT
TYPE <]
>
SETVO3: MOVE T1,DSKBLK+.DCNAM
SKIPE DSKBLK+.DCSNM
CAMN T1,DSKBLK+.DCSNM
JRST SETVO4
TYPE <[>
MOVE T1,DSKBLK+.DCUPN
PUSHJ P,SIXOUT
TYPE < is >
MOVE T1,DSKBLK+.DCULN
PUSHJ P,SIXOUT
TYPE <]
>
SETVO4: MOVE T1,DSKBLK+.DCUPN
MOVEM T1,FEUNIT
POPJ P,0
SETVO5: MOVEM T2,FAKVOL
POPJ P,
; SUBROUTINE TO MAKE FE.SYS FILE
MKFESY: MOVE T1,.FXSWT(FP) ;GET SWITCHES
TDNE T1,[S$FULL] ;FULL REQUESTED?
JRST MAKFUL ;YES, DO DIFFFERENTLY
SKIPN DSKBLK+.DCSNM ;MUST BE MOUNTED VOLUME IF NOT /FULL
ERROR <Cannot INITIALIZE an offline volume>
PUSHJ P,G10HOM ;LOAD HOME BLOCKS
DMOVE T1,HOME1+HOMFE0 ;GET THE RSX20F WORDS FROM HOME BLOCK #1
CAMN T1,HOME2+HOMFE0 ;SKIP IF COPIES DON'T MATCH
CAME T2,HOME2+HOMFE1 ;SKIP IF COPIES DO MATCH
ERROR <TOPS-10 home blocks HOMFE0/HOMFE1 don't match>
JUMPN T1,[ERROR <FE.SYS already exists>]
MOVE T1,[RB.NSE+.RBPOS] ;RB.NSE - DON'T SUPERCEED, .RBPOS=LENGTH
MOVEM T1,LERBLK+.RBCNT ;NONSUPERCEEDING ENTRY
MOVE T1,[1,,4] ;SYS:'S PPN, SAVE A GETTAB UUO
MOVEM T1,LERBLK+.RBPPN ;SPECIFY IT
MOVSI T1,'FE ' ;DEFAULT NAME
MOVEM T1,LERBLK+.RBNAM ;SPECIFY NAME OF 'FE'
MOVSI T1,'SYS' ;DEFAULT EXTENSION OF 'SYS'
MOVEM T1,LERBLK+.RBEXT ;SPECIFY EXT OF 'SYS'
SETZM LERBLK+.RBSIZ ;THIS IS IGNORED ANYWAY
MOVE T1,.JBVER ;GET OUR VERSION NUMBER
MOVEM T1,LERBLK+.RBVER ;SPECIFY AS FILE'S VERSION NUMBER
MOVE T1,[SIXBIT .RSX20F.] ;GET A SPOOLING NAME
MOVEM T1,LERBLK+.RBSPL ;SPECIFY CLEVER SPOLLING NAME
SETZM LERBLK+.RBEST ;WE NEED CONTIGUOUS FILE
SKIPN T1,V$SIZE(FP) ;GET SIZE IN BLOCKS
MOVEI T1,M.HLEN ;USE DEFAULT SIZE
MOVEM T1,V$SIZE(FP) ;FORCE A SPECIFIC SIZE
ADDI T1,3 ;2RIBS + 1 FOR LUCK
MOVEM T1,LERBLK+.RBALC ;SPECIFY ALLOCATED SIZE
MOVEM T1,REQALC ;REQUIRED ALLOCATION SIZE
PUSHJ P,MAKPOS ;GO GET THE POSITION TO PUT IT IN
MOVEM T1,LERBLK+.RBPOS ;REMEMBER IT
POSLOP: MOVSI T1,455000 ;FOOLISHLY LOW PROTECTION
MOVEM T1,LERBLK+.RBPRV ;SPECIFY EXPLICIT PRIV WORD
MOVE T1,REQALC ;GET REQUIRED SIZE
MOVEM T1,LERBLK+.RBALC ;RESPECIFY IT IN CASE OF PAO ERRORS
HLLZS LERBLK+.RBEXT ;GET RID OF JUNK FROM LAST PASS
ENTER VIO,LERBLK ;ENTER NEW FE.SYS FILE
JRST [HRRZ T1,LERBLK+.RBEXT ;GET ERROR CODE
CAIN T1,ERBNF% ;THAT BLOCK NOT FREE?
NXTCLU: JRST [MOVE T1,LERBLK+.RBPOS ;GET BLOCK WE TRIED FOR
ADD T1,CLUSIZ ;ADVANCE TO NEXT CLUSTER
JUMPL T1,POSERR ;GIVE UP IF OUT OF PLACES TO TRY
CAML T1,DSKBLK+.DCUSZ ;MAKE SURE STILL ON DISK
POSERR: ERROR <Cannot allocate at requested position>
MOVEM T1,LERBLK+.RBPOS ;UPDATE CLUSTER POSITION
MOVE T1,[S$DOTS];GET THE "I WANT DOTS" BIT
TDNE T1,.FXSWT(FP);SKIP IF I DON'T WANT DOTS
TYPE <.> ;TYPE .'S TO LET HIM KNOW WE'RE TRYING
CLOSE VIO,CL.RST;GET RID OF WRONGLY POS'D FILE
JRST POSLOP] ;AND TRY AGAIN
CAIE T1,ERPOA% ;PARTIAL ONLY?
ERROR <Cannot ENTER FE.SYS>,LSTLER
SKIPE V$INDEX(FP) ;SKIP IF NO /INDEX SWITCH
JRST NXTCLU ;DEMAND FULL SIZE IF /INDEXed
TYPE <% Only > ;WARN HIM
MOVE T1,.RBALC+LERBLK;GET SIZE WE ACTUALLY ALLOCATED
PUSHJ P,R10OUT ;TYPE SIZE THAT GOT ALLOCATED
TYPE < blocks available>
PUSHJ P,CRLF
JRST .+1]
MOVE T1,LERBLK+.RBALC ;GET ACTUAL SIZE ALLOCATED
SUBI T1,3 ;TAKE OFF BOTH RIBS + 1 FOR LUCK
MOVEM T1,V$SIZE(FP) ;AND REMEMBER THAT AS THE REAL SIZE
USETO VIO,(T1) ;WRITE ALL BLOCKS
CLOSE VIO,CL.DLL ;DON'T DEALLOCATE THE UNWRITTEN BLOCKS
TYPE <[Created >
MOVE T1,FEUNIT ;GET UNIT NAME FOR FE.SYS FILE
PUSHJ P,SIXOUT ;TYPE UNIT NAME
TYPE <:FE.SYS[1,4], > ;FAKE THE FILE NAME, EXT, AND PATH
MOVE T1,LERBLK+.RBALC ;GET SIZE ACTUALLY ALLOCATED
PUSHJ P,DECOUT ;TYPE SIZE OF FILE
TYPE < blocks allocated to FILES-11 volume]>
PUSHJ P,CRLF
MOVSI T1,'FE ' ;
MOVSI T2,'SYS' ;
SETZ T3,
MOVE T4,[1,,4]
LOOKUP VIO,T1 ;FIND FILE
ERROR <LOOKUP failed for known file>
HLLZS T2
SETZ T3,
MOVE T4,[1,,4]
ENTER VIO,T1 ;PUT FE.SYS INTO UPDATE MODE
ERROR <Can't enter update mode for FE.SYS>
USETI VIO,0 ;POSITION TO READ THE RIB
IN VIO,[IOWD 200,TMPBUF ;READ RIB INTO TEMPORARY BUFFER
0] ;...
SKIPA
ERROR <IN uuo failed while reading RIB of FE.SYS>
CLOSE VIO,CL.DLL+CL.DAT ;CLOSE IT
MOVE T1,[RP.NDL!RP.ABC] ;GET NO-DELETE BIT & BAD-CHECKSUM BIT
IORM T1,TMPBUF+.RBSTS ;TURN THEM ON
MOVE T1,.RBALC+TMPBUF
SUBI T1,2
IMULI T1,200
MOVEM T1,.RBSIZ+TMPBUF ;MAKE FILE APPEAR BIG ALREADY
MOVE T1,TMPBUF+.RBSLF ;POINT AT IT
PUSHJ P,SUSET ;POSITION TO IT
OUTPUT VIO,[IOWD 200,TMPBUF
0] ;REWRITE RIB
; ****
; **** I HAVEN'T REALLY THOUGHT ABOUT THIS VERY CAREFULLY,
; **** THIS MAY CAUSE A DIASTER IS THE OUTPUT STRUCTURE
; **** CONSISTS OF MORE THAN 1 PDP10 UNIT
AOS T1,TMPBUF+.RBSLF ;READ THE BLOCK NUMBER THAT GOT USED
TRZ T1,377 ;TURN OFF LOW BYTE
ADDI T1,400 ;COMPUTE HOME BLOCK ADDRESS
MOVEM T1,H11LBN ;AND REMEMBER IT
MOVE T1,TMPBUF+.RBSLF ;GET RIB BLOCK AGAIN
MOVEM T1,FSTLBN ;REMEMBER 1ST LBN IN VOLUME
ADD T1,V$SIZE(FP) ;COMPUTE LAST LBN IN VOLUME
SUBI T1,1
MOVEM T1,LSTLBN ;REMEMBER LAST LBN IN USE TOO
POPJ P, ;RETURN TO CALLER
MAKPOS: HLRZ T1,DSKBLK+.DCUCH ;GET CLUSTER DATA
LSH T1,-^D9 ;ISOLATE CLUSTER SIZE IN T3
MOVEM T1,CLUSIZ ;REMEMBER CLUSTER SIZE FOR SCAN
SKIPN T1,V$INDEX(FP) ;FIND VALUE OF /INDEX SWITCH
POPJ P, ;RETURN 0 FOR DON'T CARE IF NO SWITCH
CAMN T1,[SIXBIT .END.] ;END OF PACK?
JRST MAKPO1
CAMN T1,[SIXBIT .BEG.] ;BEGINNING OF PACK?
JRST MAKPO2 ;...
CAMN T1,[SIXBIT .MID.] ;MID POINT?
JRST MAKPO3
CAMN T1,[SIXBIT .BLK.] ;AT SPECIFIC BLOCK?
JRST MAKPO4 ;
ERROR <Internal error - V$INDEX isn't BEG,MID,END or BLK>
; HERE FOR /INDEX:END
MAKPO1: MOVE T1,DSKBLK+.DCUSZ ;GET SIZE OF UNIT
SUB T1,V$SIZE(FP) ;BACK OFF BY SIZE OF FILE
SUBI T1,400 ;BACK OFF FOR HOME BLOCK OFFSET
IDIV T1,CLUSIZ ;COMPUTE LOWEST CLUSTER #
IMUL T1,CLUSIZ ;COMPUTE LOWEST LBN FALLING ON CLUSTER
MOVNS CLUSIZ ;DO SCAN IN REVERSE DIRECTION
POPJ P, ;RETURN
; HERE FOR /INDEX:BEG
MAKPO2: MOVE T1,CLUSIZ ;GET FIRST CLUSTER LBN ADDRESS
POPJ P, ;(CUZ 0 MAKES MONITOR PICK IT OUT)
; HERE FOR /INDEX:MID
MAKPO3: MOVE T1,DSKBLK+.DCUSZ ;GET SIZE OF UNIT
SUB T1,V$SIZE(FP) ;BACK OFF BY SIZE OF FILE
SUBI T1,400 ;BACK OFF BY HOME BLOCK OFFSET
LSH T1,-1 ;COMPUTE RAW MIDPOINT OF IT
IDIV T1,CLUSIZ ;COMPUTE LOWEST CLUSETER #
IMUL T1,CLUSIZ ;COMPUTE LBN ADDRESS OF CLUSTER #
POPJ P, ;RETURN
; HERE FOR /INDEX:BLK
MAKPO4: MOVE T1,IDXBLK
MOVE T2,DSKBLK+.DCUSZ ;GET SIZE OF UNIT
LSH T2,-1 ;COMPUTE MIDPOINT
CAMLE T1,T2 ;
MOVNS CLUSIZ ;SCAN REVERSE IF HIGH END OF DISK
SUB T1,V$SIZE(FP) ;BACK OFF BY SIZE OF FILE
SUBI T1,400 ;BACK OFF BY MAXIMUM HOME BLOCK OFFSET
IDIV T1,CLUSIZ ;
IMUL T1,CLUSIZ
POPJ P,
; ROUTINE TO DO THE SAME WORK MKFESYS DOES WHEN USER HAS ASKED FOR /FULL
MAKFUL: TYPE <Do you really want to do a /FULL for >
MOVE T1,FEUNIT
PUSHJ P,SIXOUT
PUSHJ P,YESNO
JRST ILLCMD
TYPE <It will DESTROY THE STRUCTURE THERE, are you POSITIVE>
PUSHJ P,YESNO
JRST ILLCMD
SKIPE DSKBLK+.DCSNM
ERROR <Cannot INI/FULL an online structure>
SKIPG T1,V$SIZE(FP) ;SKIP IF HE GAVE A SIZE
MOVE T1,DSKBLK+.DCUSZ ;GET HIGHEST BLOCK #
MOVEM T1,V$SIZE(FP) ;PRETEND HE GAVE /SIZE SWITCH
MOVEM T1,LSTLBN ;SAVE IT
SETZM FSTlBN ;START WITH BLOCK 0
MOVEI T1,1 ;HOME BLOCK AT 1 FOR VMS
MOVEM T1,H11LBN
POPJ P,
; ROUTINE TO GET THE TOPS10 HOME BLOCKS IN CORE
G10HOM: SETOM HOME1+HOMNAM ;MAKE 1ST HOME BLOCK ILLEGAL
SETOM HOME2+HOMNAM ;MAKE 2ND HOM BLOCK ILLEGAL TOO
HLLZS HOME2+HOMNAM ;BUT STILL DIFFERENT FROM FIRST
MOVEI T1,1 ;1ST HOME BLOCK AT 1
PUSHJ P,SUSET ;POSITION
IN VIO,[IOWD 200,HOME1 ;READ INTO HOME BUFFER 1
0] ;
SKIPA
TYPE <% IN uuo failed reading LBN 1
>,G10HO1
G10HO1: MOVEI T1,12 ;2nd HOME BLOCK AT ^D10
PUSHJ P,SUSET
IN VIO,[IOWD 200,HOME2 ;READ INTO HOME BUFFER 2
0]
SKIPA
TYPE <% IN uuo failed reading LBN 12
>,G10HO2
G10HO2: POPJ P,
WRTHOM: SKIPN FSTLBN ;SKIP IF NOT /FULL
POPJ P, ;DON'T WRITE PDP10 HOME BLOCKS IF /FULL
MOVE T1,FSTLBN ;GET 1ST DATA BLOCK LBN OF FE.SYS
IDIVI T1,200000
IMUL T1,[1,,0]
HRR T1,T2
TLO T1,100000 ;TURN ON THE VALID BIT
MOVEM T1,HOME1+HOMFE0 ;STORE IT IN THE HOME BLOCK
MOVE T1,LSTLBN ;GET LAST BLOCK IN VOLUME
SUB T1,FSTLBN ;COMPUTE LENGTH OF VOLUME
IDIVI T1,200000
IMUL T1,[1,,0]
HRR T1,T2
MOVEM T1,HOME1+HOMFE1 ;STORE IT IN THE HOME BLOCK
ZERHOM: DMOVE T1,HOME1+HOMFE0 ;GET FE.SYS DATA
DMOVEM T1,HOME2+HOMFE0 ;STORE INTO REDUNDENT BLOCK TOO
MOVEI T1,1
PUSHJ P,SUSET
OUT VIO,[IOWD 200,HOME1
0]
SKIPA
ERROR <OUT failed writing 1st home block>
MOVEI T1,12
PUSHJ P,SUSET
OUT VIO,[IOWD 200,HOME2
0]
SKIPA
ERROR <OUT failed writing 2nd home block>
POPJ P,0
SUBTTL TERMINAL I/O
SIXOUT: SETZ T2, ;MAKE ROOM
ROTC T1,6
MOVEI T3,40(T2)
PUSHJ P,TYO
JUMPN T1,SIXOUT
POPJ P,0
;ROUTINE TO PRINT OUT THE "PROTECTION" INDICATED BY T1
P11OUT: PUSHJ P,SAVE2 ;SAVE SOME ACS
MOVEI T3,"<" ;
MOVEI T2,">" ;DUMMY
PUSHJ P,TYO
PUSH P,T1 ;SAVE IT A SECOND
PUSHJ P,OCTOUT ;TYPE IT
POP P,T1 ;RESTORE IT
TYPE <=> ;EQUATE IT
MOVEI P1,4 ;4 GROUPS
SKIPA
P11OU1: TYPE <,> ;SEPERATE GROUPS
TRNN T1,1 ;READ INHIBITED?
TYPE <R> ;NO, READ PERMITTED
TRNN T1,2 ;WRITE INHIBITED?
TYPE <W> ;NO, WRITE PERMITTED
TRNN T1,4 ;EXTEND INHIBITED?
TYPE <E> ;NO, EXTEND PERMITTED
TRNN T1,10 ;DELETE INHIBITED?
TYPE <D> ;NO, DELETE PERMITTED
LSH T1,-4 ;GET NEXT GROUP
SOJG P1,P11OU1 ;LOOP FOR NEXT GROUP
MOVEI T2,"<" ;
MOVEI T3,">" ;
PJRST TYO ;EXIT
;ROUTINE TO TYPE FILE NAME WITHOUT TRAILING SPACES
;
; T1/ 1ST 3RD OF FILE NAME
; T2/ 2ND 3RD
; T3/ 3RD 3RD
FILE5O: PUSHJ P,SAVE4
DMOVE P1,T1
MOVE P3,T3
SETZ P4,
PUSHJ P,SPIT3
MOVE T1,P2
PUSHJ P,SPIT3
MOVE T1,P3
PUSHJ P,SPIT3
POPJ P,
SPIT3: IDIVI T1,^O50*^O50
IDIVI T2,^O50
PUSHJ P,SPIT1
MOVE T1,T2
PUSHJ P,SPIT1
MOVE T1,T3
SPIT1: JUMPE T1,[AOJA P4,CPOPJ]
JUMPE P4,SPIT0
PUSH P,T3
MOVEI T3," "
PUSHJ P,TYO
POP P,T3
SOJA P4,SPIT1
SPIT0: PUSHJ P,RAD5O
POPJ P,
;TYPE T1 AS 3 RADIX 50 CHARACTERS
RAD53O: IDIVI T1,^O50*^O50
IDIVI T2,^O50
PUSH P,T3
PUSH P,T2
PUSHJ P,RAD5O
POP P,T1
PUSHJ P,RAD5O
POP P,T1
RAD5O: PUSH P,T3
MOVE T3,R2STBL(T1)
ADDI T3,40
PUSHJ P,TYO
POP P,T3
POPJ P,
;ROUTINES TO TYPE T1 AS A DECIMAL NUMBER
DECOUT: PUSHJ P,R10OUT ;TYPE NONFILLED DECIMAL NUMBER
MOVEI T3,"." ;AND THEN...
PUSHJ P,TYO ;TYPE A DOT TO SHOW IT'S DECIMAL
POPJ P,0 ;EXIT
;ROUTINE TO TYPE AN UNFILLED DECIMAL NUMBER
R10OUT: IDIVI T1,^D10
PUSH P,T2
CAIE T1,0
PUSHJ P,R10OUT
POP P,T2
MOVEI T3,"0"(T2)
PUSHJ P,TYO
POPJ P,
;ROUTINE TO TYPE A DECIMAL NUMBER WITH AT LEAST 2 DIGITS
DECO2: CAIG T1,^D9
TYPE < >
JRST DECOUT
DECO3: CAIG T1,^D99
TYPE < >
JRST DECO2
DECO4: CAIG T1,^D999
TYPE < >
JRST DECO3
DECO5: CAIG T1,^D9999
TYPE < >
JRST DECO4
; ROUTINE TO TYPE OUT A "SEQUENCE NUMBER" TO THE OUTPUT FILE
TYPSQN: PUSHJ P,SAVE4 ;SAVE SOME ACS
MOVE P1,T3 ;COPY THE SEQUENCE NUMBER
MOVEI T3,0 ;GET A ZERO
MOVE P2,PUTCTR ;GET COUNTER
IDIVI P2,5 ;FIND OUT WHERE WE ARE
SKIPE P3 ;WE AT THE RIGHT BOUNDRY
JRST [PUSHJ P,XPUTC ;PAD OUT
JRST .-3] ;UNTILL WE ARE AT THE RIGHT BOUNDRY
MOVE T1,P1 ;GET SEQUENCE NUMBER
MOVEI P1,5 ;ALWAYS EXACTLY 5 DIGITS
TYPSQ1: IDIVI T1,^D10 ;GET ANOTHER DIGIT
PUSH P,T2 ;SAVE REMAINDER
SOSLE P1 ;SKIP IF END OF NUMBER
JRST TYPSQ1 ;LOOP FOR ANOTHER DIGIT
MOVEI P1,5 ;5 DIGITS AGAIN
TYPSQ2: POP P,T3
ADDI T3,"0" ;CONVERT TO ASCII
PUSHJ P,PUTC ;PUT IT IN FILE
SOJG P1,TYPSQ2 ;LOOP FOR ALL DIGITS
MOVE T1,DOBUF+.BFPTR ;GET POINTER TO LAST DIGIT
MOVEI T2,1 ;GET LINE # BIT
IORM T2,(T1) ;TURN IT ON
POPJ P, ;RETURN
;ROUTINE TO TYPE T1 AS OCTAL NUMBER
OCTOUT: IDIVI T1,^O10
PUSH P,T2
CAIE T1,0
PUSHJ P,OCTOUT
POP P,T2
MOVEI T3,"0"(T2)
PUSHJ P,TYO
POPJ P,0
;...AS OCTAL USING AT LEAST 2 DIGITS
OCTO2: CAIG T1,^O7
TYPE < >
JRST OCTOUT
OCTO3: CAIG T1,^O77
TYPE < >
JRST OCTO2
OCTO4: CAIG T1,^O777
TYPE < >
JRST OCTO3
OCTO5: CAIG T1,^O7777
TYPE < >
JRST OCTO4
OCTO6: CAIG T1,^O77777
TYPE < >
JRST OCTO5
OCTO7: CAIG T1,^O777777
TYPE < >
JRST OCTO6
;ROUTINE TO TYPE THE CURRENTLY OPENED VOLUME
VOLOUT: MOVE T1,FEUNIT ;GET PHYSICAL UNIT
SKIPE T2,FAKVOL ;SKIP IF REAL UNIT IN USE
MOVE T1,VOLTBL(T2) ;ELSE GET LOGICAL NAME
PUSHJ P,SIXOUT
TYPE <:>
POPJ P,
;ROUTINE TO TYPE T1 AS A PPN
PPNOUT: PUSH P,T1
TYPE <[>
HLRZ T1,(P)
PUSHJ P,OCTOUT
TYPE <,>
POP P,T1
HRRZS T1
PUSHJ P,OCTOUT
TYPE <]>
POPJ P,
;ROUTINE TO TYPE A CRLF TO OUTPUT
; LESS MESSY THAN INCLUDING A CRLF IN TYPEOUT LITERALS
CRLF: TYPE <
>
POPJ P,0
FCRLF: PUSH P,T3
MOVEI T3,15
PUSHJ P,PUTC
MOVEI T3,12
PUSHJ P,PUTC
POP P,T3
POPJ P,
;ROUTINE TO READ IN A SINGLE CHARACTER FROM THE KEYBOARD
TYI: MOVE T3,LASTCH ;GET LAST CHARACTER IN CASE OF RE-EAT
TDZE F,[X%REEAT] ;RETURN IT?
JRST TYI1 ;YES, DO IT
INCHWL T3 ;GET A CHARACTER
CAIN T3,15 ;BUT REJECT A CR AND TRY FOR LF
JRST TYI ;...
TYI1: MOVEM T3,LASTCH ;REMEMBER LAST CHARACTER RETURNED
POPJ P,0
;ROUTINE TO READ IN A SINGLE CHARACTER FROM THE KEYBOARD
;...AND CONVERT TO UPPERCASE ALPHABETIC IF LOWERCASE ALPHABETIC
TYIUC: PUSHJ P,TYI ;GET CHARACTER
CAIL T3,"a" ;AND CHECK FOR LOWER CASE
CAILE T3,"z" ;...?
POPJ P, ;UPPER, JUST RETURN
SUBI T3,40 ;CONVERT LOWER TO UPPER
POPJ P,
;ROUTINE TO READ IN A SINGLE CHARACTER FROM THE KEYBOARD
;...BUT TO SKIP OVER ANY LEADING WHITE SPACE
TYINB: MOVE T3,LASTCH ;ALREADY GOT ONE?
CAIE T3," " ;SKIP IF LAST WAS BLANK
CAIN T3," " ;SKIP IF LAST WAS TAB
JRST [PUSHJ P,TYIUC ;IF LEADING WHITE SPACE, GOBBLE IT, TRY AGAIN
JRST TYINB] ;NO, GET ONE
POPJ P, ;THATS ALL
; ROUTINE TO SETUP AN OUTPUT FDB, IF ANY
SETOUT: MOVE T1,.FXMOD(FP) ;GET FLAGS FOR THIS SPEC
TDNE T1,[FX.EQL] ;= SEEN?
JRST SETOU1 ;YES, SET REAL OUTPUT FILE
HRLZI T1,'* ' ;WILD CARD FILE NAME
MOVEM T1,.FXNAM+OUTFDB ;
SETZM .F2NAM+OUTFDB ;...
MOVEM T1,.FXEXT ;WILD FILE TYPE
SETZM .FXNMM+OUTFDB
SETZM .F2NMM+OUTFDB
SETZM .FXDIR+OUTFDB
SETZM .FXDIR+2+OUTFDB
SETOM .FXDIM+OUTFDB
SETZM .FXDEV+OUTFDB
POPJ P,
SETOU1: MOVSI T1,(FP)
HRRI T1,OUTFDB
BLT T1,OUTFDB+.FXLEN-1
HRRZ FP,.FXLNK(FP)
JUMPE FP,[ERROR <File specification required to define input>]
POPJ P,
; ROUTINE TO SETUP WHERE "TTY," GOES TO
;
; IF THE STATIC FILE SPEC SHOWS AN "=" SIGN, THEN USE IT AS OUTPUT
; OTHERWISE, USE PHYSICAL TTY:
SETTTY: MOVE T1,.FXMOD(FP) ;GET FLAGS FOR CURRENT FILE SPEC
TDNE T1,[FX.EQL] ;= SEEN?
JRST SETTT1 ;YES, SETUP REAL OUTPUT FILE
TTYPHY: TDO F,[X%INT] ;AN INTERACTIVE DEVICE
MOVE T1,[UU.PHS!.IOASC] ;NO, PREPARE FOR TTY
MOVSI T2,'TTY' ;
MOVSI T3,TTYOBF ;
OPEN TTY,T1 ;OPEN TTY FOR OUTPUT
HALT . ;THIS MUST NOT HAPPEN
OUTBUF TTY,1 ;ONLY ONE BUFFER, ALLOCATE IT NOW
POPJ P, ;WE'RE DONE
SETTT1: TDZ F,[X%INT] ;NOT AN INTERACTIVE DEVICE
SKIPE .F2NAM(FP) ;MUST BE SHORT FILE NAME
ILLFL0: ERROR <Illegal output file name>
SKIPE .FXNAM(FP)
AOSN .FXNMM(FP)
SKIPA
JRST ILLFL0
SETOM .FXNMM(FP)
MOVE T2,CMDIDX
SKIPN T1,.FXNAM(FP) ;HE GIVE EXPLICIT FILE NAME?
MOVE T1,CMDSIX(T2)
MOVEM T1,.FXNAM(FP) ;REMEMBER WHATEVER FILE NAME
SKIPN T1,.FXEXT(FP) ;SKIP IF HE GAVE NO EXT
HRLOI T1,'OUT' ;NO, USE .OUT
MOVEM T1,.FXEXT(FP) ;REMEMBER FINAL EXT WE CHOSE
HRRES T1 ;EXTEND WILD CARD MASK
AOJN T1,[ERROR <Illegal output file extension>]
MOVEI T1,(FP) ;POINT AT FILE SPEC BLOCK
MOVEI T2,OPNBLK ;POINT AT OPEN BLOCK
MOVEI T3,LERBLK ;POINT AT L/E/R BLOCK
MOVEI T4,PTHBLK ;POINT AT PATH BLOCK
PUSHJ P,.STOPB## ;GO BUILD UP THE UUO BLOCKS
ERROR <Cannot "setup" log output file>
MOVEI T1,.IOASC
MOVEM T1,OPNBLK+0
MOVSI T1,TTYOBF
MOVEm T1,OPNBLK+2
OPEN TTY,OPNBLK ;OPEN CHANNEL FOR OUTPUT
ERROR <Cannot OPEN output device>
MOVEi T1,.RBSPL
MOVEm T1,LERBLK
ENTER TTY,LERBLK ;
ERROR <ENTER failed for output file>,LSTLER
OUTBUF TTY,1 ;ONLY USE 1 BUFFER
HRRZ FP,.FXLNK(FP) ;STEP TO 1ST INPUT SPEC
JUMPE FP,[ERROR <Input specification required>]
POPJ P, ;RETURN
; ROUTINE TO READ IN A FILE SPEC PLUS ANY LEADING/TRAILING SWITCHES
;
;RETURN:
; T1/ POINTER TO FILE SPEC BLOCK
FILIN: PUSHJ P,SAVE4 ;SAVE P1-P4
PUSHj P,SAVFP
SETZM IPLIST ;START OFF WITH NO INPUT
SETZM IPLAST ;...
FILINL: PUSHJ P,TRMSKP ;END OF LINE?
SKIPA ;NO, ALL'S OK
POPJ P, ;GIVE NO FILES RETURN
MOVEI FP,STATIC ;MAKE FILIN USE THE STATIC FDB
PUSHJ P,FILINZ ;GO GET A FILE SPEC
MOVE T1,.FXDEV+STATIC ;GET DEVICE
IOR T1,.FXNAM+STATIC ;AND FILE NAME
IOR T1,.FXEXT+STATIC ;AND EXT
MOVE T2,.FXMOD+STATIC ;AND MODIFIER
SKIPN T1 ;ANY PART OF FILE SPEC
TDNE T2,[FX.CMA!FX.EQL] ;OR ANY REASON TO IMPLY ONE?
SKIPA ;SKIP IF SOME SORT OF FILE SPEC SEEN
POPJ P, ;JUST RETURN IF NO FILE SPEX
MOVEI T1,.FXLEN ;SIZE OF A FILE SPEC
PUSHJ P,GETCOR ;GO ALLOCATE ONE
SKIPN IPLIST ;IS THIS THE 1ST?
MOVEM T1,IPLIST ;YES, REMEMBER IT
SKIPE T2,IPLAST ;IS THERE A LAST ONE?
MOVEM T1,.FXLNK(T2) ;YES, REMEMBER THE LINK TO THIS ONE
MOVEM T1,IPLAST ;REMEMBER THIS BLOCK FOR NEXT TIME
HRLI T1,STATIC
MOVEI T2,.FXLEN-1(T1) ;LAST WORD TO MOVE
BLT T1,(T2) ;MOVE THE FILE SPEC TO PERMANENT PLACE
JRST FILINL ;LOOP
FILINZ: SETZM (FP) ;CLEAR THE FILE BLOCK
MOVEI T1,1(FP) ;
HRLI T1,(FP)
BLT T1,.FXLEN-1(FP) ;...CLEAR ENTIRE BLOCK TO ZEROES
MOVE T1,[FX.NDV]
IORM T1,.FXMOD(FP)
FILIN1: PUSHJ P,SIXIN ;READ A POSSIBLE FILE NAME
CAIN T3,":" ;TERMINATING CHARACTER ":"?
JRST FILIN3 ;YES, GO PARSE OFF A DEVICE NAME
JUMPE T4,FILIN2 ;SKIP IF NO FILE NAME THERE
SKIPE STATIC+.FXNAM ;SKIP IFF NEVER SEEN FILE NAME
ERROR <Illegal file name>
MOVEM T1,STATIC+.FXNAM ;SAVE FILE NAME
MOVEM T2,STATIC+.F2NAM ;SAVE ALL OF FILE NAME
MOVEM M1,STATIC+.FXNMM ;SAVE NAME MASK
MOVEM M2,STATIC+.F2NMM ;SAVE 2ND NAME MASK
FILIN2: CAIE T3," " ;SKIP IFF ENDED WITH BLANK
CAIN T3," " ;SKIP IFF ENDED WITHOUT BLANK OR TAB
JRST FILIN1 ;LOOP IF BLANK OR TAB
CAIN T3,"." ;FILE TYPE COMING UP?
JRST FILIN4 ;YES, GO GET FILE TYPE
CAIN T3,"[" ;FILE PATH/UIC COMING UP?
JRST FILIN5 ;YES, GO GET PATH/UIC
CAIN T3,"<" ;PDP10 PROTECTION FIELD COMING? ">"
JRST FILIN8 ;YES, GO GET PDP10 PROTECTION
CAIN T3,"/" ;SWITCH COMING UP?
JRST FILIN9 ;YES, GO GET SWITCH
CAIN T3,";" ;GENERATION COMING UP?
JRST FILING ;YES, GO GET IT
;HERE WHEN WE CANNOT PARSE ANYTHING MORE FROM FILE SPECIFICATION
MOVE T1,[FX.EQL] ;EQUAL SEEN BIT
CAIN T3,"=" ;EQUAL SEEN?
IORM T1,STATIC+.FXMOD ;REMEMBER SEEN WITH THAT SPEC
MOVE T1,[FX.CMA] ;COMMA SEEN BIT
CAIN T3,"," ;COMMA SEEN?
IORM T1,STATIC+.FXMOD ;REMEBER COMMA SEEN
; THIS SECTION SAVES TIME AND DOES THE INITIAL WILD CARDING
; ON THE INPUT FILE NAMES
POPJ P, ;RETURN
;HERE TO GET OCTAL GENERATION NUMBER
FILING: PUSHJ P,OCTIN ;GO GET THE GENERATION NUMBER
JUMPE T4,ILLCHR ;SHOULD BE AT LEAST 1 DIGIT IN IT
AOJN M1,ILLCHR ;MUST NOT BE WILD
CAILE T1,0 ;0 OR -VE VERSIONS NOT PERMITTED
CAILE T1,77777 ;15 BITS OR LESS OF VERSION
ERROR <Illegal version number specified>
MOVEM T1,.FXGEN(FP) ;SAVE THE GENERATION NUMBER
JRST FILIN2 ;CONTINUE PARSE
;HERE TO GET A DEVICE NAME
FILIN3: JUMPN T2,ILLDEV ;IF MORE THAN 6 CHARS, ITS BAD
AOJN M1,ILLDEV ;MUST BE NO WILD CHARACTERS
SKIPE STATIC+.FXDEV ;SKIP IFF 1ST DEVICE NAME SEEN
ILLDEV: ERROR <Illegal device> ;...THAT IS ALSO BAD
MOVEM T1,STATIC+.FXDEV ;SAVE DEVICE NAME
MOVE T1,[FX.NDV]
ANDCAM T1,.FXMOD(FP)
JRST FILIN1 ;TRY TO GET ANOTHER FIELD
;HERE TO GET A FILE EXTENSION
FILIN4: SKIPE STATIC+.FXEXT ;SKIP IF NOT FILE TYPE SEEN BEFORE
ILLEXT: ERROR <Illegal extension> ;
PUSHJ P,SIXIN ;GET THE EXTENSION
CAILE T4,3 ;NEVER MORE THAN 3 CHARACTERS
JRST ILLEXT ;COMPLAIN IF MORE THAN 3
HLLZM T1,STATIC+.FXEXT ;SAVE EXTENSION NAME
HLRM M1,STATIC+.FXEXT ;SAVE EXTENSION WILD INFO
JRST FILIN2 ;GO GET ANOTHER FIELD
;HERE TO GET A FILE PATH/UIC/DIRECTORY
FILIN5: MOVE T1,[FX.DIR] ;GET THE DIRECTORY SEEN BIT
TDNE T1,STATIC+.FXMOD ;SKIP IF DIRECTORY NEVER SEEN
JSP U0,ILLPPN ;GO COMPLAIN IF MULTIPLE DIRECTORIES
IORM T1,STATIC+.FXMOD ;SET THE DIRECTORY SEEN BIT
PUSHJ P,SIXIN ;GET FIRST WORD OF STUFF
CAIE T3,"," ;IF UIC/PPN, MUST BE COMMA
JRST FILIN7 ;BRANCH IF NOT UIC/PPN
PUSHJ P,C6T8 ;CONVERT TO OCTAL
JSP U0,ILLPPN ;GO COMPLAIN
HRLZM T1,STATIC+.FXDIR ;STORE DIRECTORY #
HRLM M1,STATIC+.FXDIM ;STORE DIRECTORY # MASK
PUSHJ P,OCTIN ;GET SECOND PART OF STUFF
HRRM T1,STATIC+.FXDIR ;STORE IN DIRECT #
HRRM M1,STATIC+.FXDIM ;STORE IN DIRECT # MASK
SETZM STATIC+.FXDIN+1
SETOM STATIC+.FXDNM+1
MOVE T1,STATIC+.FXDIR ;GET DIRECTORY #
MOVE M1,STATIC+.FXDIM ;GET DIRECTORY # MASK
PUSHJ P,MAKUIC ;GO MAKE IT INTO AN UIC NAME
MOVEM T1,STATIC+.FXDIN ;SAVE DIRECTORY NAME
MOVEM M1,STATIC+.FXDNM ;SAVE DIRECTORY NAME MASK
MOVE T3,LASTCH ;PRIME IT
MOVE P1,[-5,,STATIC+.FXDIR+2];POINT AT SFD LIST
FILIN6: SKIPGE P1 ;DON'T ZERO MEMORY OUTSIDE SFD LIST
SETZM (P1) ;MAKE SURE LIST ENDS IN 0
CAIE T3,"," ;SFD PATH LIST COMING?
JRST [CAIN T3,"]"
JRST FILIN1 ;LOOP IF PPN LIST ENDED PROPERLY
TDO F,[X%REEAT] ;ELSE SETUP TO REEAT SEPERATOR
JRST FILIN1] ;...AND THEN LOOP
PUSHJ P,SIXIN ;GET A SFD NAME
CAILE T4,6 ;SFD MUST BE 6 CHARACTERS OR LESS
JSP U0,ILLPPN ;GO COMPLAIN IF SFD NAME TOO BIG
SKIPGE P1 ;DON'T SAVE SFD NAMES BEYOND LEGAL DEPTH
MOVEM T1,(P1) ;SAVE SFD NAME
SKIPGE P1 ;DON'T SAVE SFD MASKS BEYOND LEGAL DEPTH
MOVEM M1,.FXDIM-.FXDIR(P1) ;SAVE SFD MASK
AOBJN P1,[AOJA P1,FILIN6] ;LOOP FOR MORE SFD NAMES
JRST FILIN6 ;LOOP FOR MORE
;HERE IF PATH SPEC IS SCREWY, IF DEBUGGING LOOK AT U0 FOR CALLER'S ADDRESS
ILLPPN: ERROR <Illegal format for PPN or UIC>
;HERE IF NO COMMA SEEN - MUST BE A "DIRECTORY NAME"
FILIN7: DMOVEM T1,STATIC+.FXDIN ;STORE IN DIRECTORY-NAME
DMOVEM M1,STATIC+.FXDNM ;STORE IN DIRECTORY-NAME-MASK
CAIE T3,"]"
TDO F,[X%REEAT] ;REEAT TERMINATOR IF NOT ]
JRST FILIN1 ;RESUME EATING THIS FILE SPEC
;HERE TO READ IN PROTECTION FIELD
FILIN8: PUSHJ P,TYIUC ;GET NEXT CHARACTER
CAIL T3,"0" ;SKIP IF NOT NUMERIC PROTECTION
CAILE T3,"7" ;SKIP IF NUMERIC PROTECTION
JRST FIL8B ;GO READ RWED STYLE PROTECTION
TDO F,[X%REEAT] ;RE-EAT THE FIRST DIGIT
PUSHJ P,OCTIN ;GO GET THE NUMERIC PROTECTION CODE
CAIN T4,3 ;MUST BE EXACTLY 3 DIGITS
CAIE T3,">" ;...AND MUST END WITH >
ERROR <Illegal character in protection field>
AOJN M1,.-1 ;BRANCH IF USER SAID <???>
LDB T2,[POINTR(.FXMOD(FP),FX.PRO)]
JUMPN T2,[PUSHJ P,ILLCMD];BRANCH TO COMPLAIN IF NOT 1ST PROTECTION
DPB T1,[POINTR(.FXMOD(FP),FX.PRO)] ;INSERT THE PROTECTION INTO FDB
JRST FILIN1 ;LOOP FOR REMAINDER OF SPEC
;HERE TO READ SYMBOLIC RWED PROTECTION CODE
FIL8B: PUSHJ P,PRTIN
MOVEM T1,V$FPRO(FP)
JRST FILIN1
;HERE TO READ IN SWITCH
FILIN9: PUSHJ P,SIXIN ;GET SWITCH NAME
SKIPN T2 ;NOT MORE THAN 6 CHARS
AOSE M1 ;SKIP IF NOT WILD
ILLSWT: ERROR <Illegal switch>
PUSHJ P,FNDIDX
CAI SWTSIX
JUMPL T1,ILLSWT
MOVE T2,SWTBIT(T1) ;GET THE BIT
IORM T2,.FXSWT+STATIC
CAIN T3,":" ;ANY INDICATION WE SHOULD DO IT?
PUSHJ P,@SWTSRV(T1) ;GO SERVICE THE ARG, IF ANY
JRST FILIN2
; SOME SWITCH TABLE DATA
DEFINE S(.name,.serve),<SIXBIT @'.name'@>
SWTSIX: SS
0
DEFINE S(.name,.serve<ILLSWT>),<EXP .serve>
SWTSRV: SS
DEFINE S(.name,.serve),<S$'.name'==.bit
EXP S$'.name'
.BIT==.BIT_-1>
.bit==1B0
SWTBIT: SS
; HERE TO READ A PDP11 PROTECTION CODE
PRTIN: PUSHJ P,SAVE2 ;SAVE SOME ACS
SETZ P1, ;START OFF
MOVEI P2,4 ;# OF GROUPS
NXTGRP: LSH P1,-4 ;MAKE ROOM FOR NEXT GROUP
TRO P1,170000 ;START OFF WITH EVERYTHING INHIBITED
SOJL P2,[ERROR <Too many protection groups>]
REDGRP: PUSHJ P,TYIUC
CAIN T3,"," ;GROUP SEPERATOR?
JRST NXTGRP ;YES, START NEXT GROUP
CAIN T3,">" ;PROTECTION END?
JRST ENDPRO ;YES
CAIN T3,"R" ;
HRROI T3,10000
CAIN T3,"W"
HRROI T3,20000
CAIN T3,"E"
HRROI T3,40000
CAIN T3,"D"
HRROI T3,100000
JUMPGE T3,[ERROR <Illegal character in protection group>]
TDZ P1,T3 ;TURN OFF INHIBIT BIT
JRST REDGRP
ENDPRO: JUMPN P2,[ERROR <Too few protection groups>]
MOVE T1,P1 ;RETURN IT IN T1
POPJ P,
FPRTIN: PUSHJ P,PRTIN
MOVEM T1,V$FPRO(FP)
POPJ P,
VPRTIN: PUSHJ P,PRTIN
MOVEM T1,V$VPRO(FP)
POPJ P,
; HERE TO READ /FILENUMBER:nnn SWITCH
FILEIN: PUSHJ P,DECIN ;GET FILE NUMBER
SKIPLE T1 ;FILES -VE OR 0 NOT LEGAL
CAIG T1,4 ;IN FACT, DON'T DELETE 0-4 EITHER
JRST ILLSWT
CAIL T1,200000 ;AND DON'T ALLOW MORE THAN FILE #S
JRST ILLSWT
MOVEM T1,V$FILE(FP) ;SAVE FILE #
POPJ P,
; HERE TO READ /ALLOC:nnn SWITCH
ALCIN: PUSHJ P,DECIN ;GET SIZE
CAIL T1,177777 ;PLEASE, NO MORE THAN POSSIBLE # FILES
JRST ILLSWT ;BAD VALUE
MOVEM T1,V$ALLOC(FP) ;SAVE VALUE
POPJ P,
; HERE TO READ ARGUMENT FOR /EXTEND SWITCH
EXTDIN: PUSHJ P,DECIN
CAILE T1,0
CAIL T1,^D128
JRST ILLSWT
MOVEM T1,V$EXTE(FP)
POPJ P,
; HERE TO READ ARGUMENT FOR /SIZE SWITCH
SIZIN: PUSHJ P,DECIN
CAIGE T1,400
JRST ILLSWT
MOVEM T1,V$SIZE(FP)
POPJ P,
; HERE TO READ ARGUMENT FOR /MAXFIL
MAXFIN: PUSHJ P,DECIN
CAIL T1,5 ;MUST BE AT LEAST 5 FILES!!
CAILE T1,177777 ;AND CANNOT EXCEED FIELD SIZE!
JRST ILLSWT
MOVEM T1,V$MAXFIL(FP)
POPJ P,
; HERE TO READ ARGUMENT FOR /INDEX
IDXIN: PUSHJ P,SIXIN
PUSHJ P,FNDIDX
CAI IDXSIX
JUMPL T1,ILLSWT
MOVE T1,IDXSIX(T1)
MOVEM T1,V$INDEX(FP)
CAME T1,[SIXBIT .BLK.]
POPJ P,
MOVE T3,LASTCH
CAIE T3,":"
JRST ILLSWT
PUSHJ P,OCTIN
AOJN M1,ILLCHR
JUMPE T1,ILLCHR
MOVEM T1,IDXBLK
POPJ P,
IDXSIX: 'BEG '
'MID '
'END '
'BLK '
0
ILLCHR: ERROR <Illegal character>
ILLNUM: ERROR <Ilegal digit>
; HERE TO READ ARG FOR /CHARACTERISTICS
CHAIN: PUSHJ P,SIXIN
PUSHJ P,FNDIDX
CAI CHASIX
JUMPL T1,ILLSWT
MOVE T1,CHABIT(T1)
IORM T1,V$CHAR(FP)
POPJ P,
CHASIX: 'ATTACH'
'DCFUNC'
0
CHABIT: 20
10
; ROUTINE TO READ IN A SIXBIT STRING, UP TO 12 CHARACTERS
;
; PUSHJ P,SIXIN
; <ALWAYS RETURN HERE, T1/ 1ST 6 CHARACTERS OF STRING
; T2/ 2ND 6 CHARACTERS OF STRING
; M1/ 1ST 6 CHARACTERS OF MASK FOR STRING IN T1
; M2/ 2ND 6 CHARACTERS OF MASK, FOR STRING IN T2
; T3/ TERMINATING CHARACTER
; T4/ COUNT OF ACTUAL CHARACTERS IN STRING>
SIXIN: SETZB T1,T2 ;START OFF WITH NULL STRING
SETOB M1,M2 ;START OFF WITH NO WILD CHARACTERS
MOVE U0,[POINT 6,T1] ;POINT AT TOP OF STRING
SETZ T4, ;ZERO COUNT OF CHARACTERS
SIXILP: PUSHJ P,TYIUC ;GET A CHARACTER, UPPER CASE ONLY
CAIE T3," " ;SKIP IFF CHARACTER IS A BLANK
CAIN T3," " ;SKIP IFF CHARACTER IS NOT BLANK OR TAB
JUMPE T4,SIXILP ;IGNORE LEADING BLANKS, TABS
CAIN T3,"?" ;WILD CARD?
JRST SIXIN2 ;YES, SKIP LEGALITY CHECK
CAIN T3,"*" ;WILD CARD?
JRST SIXIN3 ;YES, SKIP LEGALITY CHECK
CAIL T3,"0" ;SKIP IF OUT OF POSSIBLE SIXBIT RANGE
CAILE T3,"9" ;SKIP IFF IN RANGE OF SIXBIT DIGIT
CAIL T3,"A" ;SKIP IF OUT OF RANGE OF POSSIBLE SIXBIT
CAILE T3,"Z" ;SKIP IF IN RANGE OF SIXBIT DIGIT OR LETTER
POPJ P,0 ;RETURN IF OUT OF SIXBIT RANGE
SIXIN2: TRNE T2,77 ;SKIP IF STRING NOT YET FULLY FULL
JRST SIXILP ;BRANCH IF NO MORE ROOM, JUST EAT THIS CHARACTER
SUBI T3,40 ;CONVERT CHARACTER TO SIXBIT
IDPB T3,U0 ;INSERT THE CHARACTER
CAIN T3,'?' ;WILD CHARACTER?
PUSHJ P,[ADDI U0,M1-T1; POINT U0 AT THE PARALLEL MASK WORD
MOVEI T3,00 ; GET THE VALUE FOR "WILD"
DPB T3,U0 ; STORE A WILD MARKER IN THE MASK WORD
SUBI U0,M1-T1; RE-POINT U0 BACK AT INPUT WORD
POPJ P,0]
AOJA T4,SIXILP ;AND COUNT IT
;HERE IF WE SEE A "*"
SIXIN3: MOVEI T3,^D9 ;SAY WE GOT ALL 9 CHARACTERS
CAILE T4,^D9 ;UNLESS THATS FALSE
MOVEI T3,^D12 ;THEN SAY WE GOT 12
SUB T3,T4 ;GET NUMBER REMAINING
PUSH P,T3 ;SAVE COUNTER
SIXIN4: SOSGE (P) ;COUNT IT
JRST SIXIN5
MOVEI T3,'?'
IDPB T3,U0 ;STORE IT
ADDI U0,M1-T1
MOVEI T3,00
DPB T3,U0
SUBI U0,M1-T1
JRST SIXIN4 ;DON'T COUNT THE "?"
SIXIN5: POP P,T3
AOJA T4,SIXILP ;COUNT ONE MORE CHARACTER
; ROUTINE TO ACCEPT YES OR NO
YESNO: PUSHJ P,SKEOL ;GET RID OF TYPE AHEAD
YESNO1: CLRBFI ;REALLY GET RID OF IT
TYPE <, YES or NO? >
OUTPUT TTY,
PUSHJ P,SIXIN ;READ RESPONSE
AOJN M1,ILLYES ;WILD CHARACTERS MEAN NO
PUSHJ P,TRMSKP ;MUST NOT BE GARBAGE ON THE LINE
ILLYES: ERROR <Abort via NO>
CAME T1,[SIXBIT .Y.] ;ACCEPT ONLY "Y"
CAMN T1,[SIXBIT .YES.];OR "YES"
JRST CPOPJ1
CAMN T1,[SIXBIT .YE.]
JRST YESNO1 ;CONSIDER ACCEPTING "YE"
JRST ILLYES
SKEOL0: PUSHJ P,TYI ;GET ANOTHER CHARACTER
SKEOL: PUSHJ P,TRMSKP ;LAST CH AN EOL?
JRST SKEOL0 ;NO, TRY NEXT ONE THEN
POPJ P, ;YES, JUST RETURN
;ROUTINE TO READ A DECIMAL NUMBER INTO T1, DIGIT COUNT INTO T2
DECIN: SETZB T1,T2
DECILP: PUSHJ P,TYI
CAIL T3,"0"
CAILE T3,"9"
POPJ P,0
IMULI T1,^D10
ADDI T1,-"0"(T3)
AOJA T2,DECILP
; ROUTINE TO READ AN OCTAL NUMBER FROM THE KEYBOARD
;
; PUSHJ P,OCTIN
; <ALWAYS RETURN HERE, T1/ VALUE
; M1/ MASK
; T3/ TERMINATING CHARACTER
; T4/ COUNT OF VALID DIGITS>
OCTIN: SETZ T1,
SETO M1,
SETZ T4,
OCTILP: PUSHJ P,TYI
CAIN T3,"?"
JRST OCTQST
CAIN T3,"*"
JRST OCTSTR
CAIL T3,"0"
CAILE T3,"7"
POPJ P,0
CAIL T4,6
ERROR <Illegal number>
IMULI T1,^O10
IMULI M1,^O10
ADDI T1,-"0"(T3)
TRO M1,7
AOJA T4,OCTILP
OCTQST: CAILE T4,6
JRST ILLNUM
IMULI T1,^O10
IMULI M1,^O10
ADDI T1,7
; TRZ M1,7
AOJA T4,OCTILP
OCTSTR: JUMPN T4,ILLCHR
CAILE T4,6
JRST ILLNUM
SETO T1, ;set #=all 7s
SETZ M1, ;set mask = all wild
MOVEI T4,6
JRST OCTILP
;ROUTINE TO CONVERT T1/T2 V M1/M2 SIXBIT INTO T1 V M1 OCTAL
;SKIP RETURN IF LEGAL OCTAL, NONSKIP IF NOT
QC6T8: MOVEI T4,6 ;ALWAYS ASSUME 6
C6T8: PUSHJ P,SAVE4 ;P1=RESULT,P2=BP TO T1/T2, P3=COPY OF T4
SETZ P1, ;START RESULT=0
SETO M1, ;NOT AT ALL WILD
MOVE P3,T4 ;COPY THE COUNT
JUMPE T4,C6T8Z ;EXIT QUIKLY IF NO CHARACTERS AT ALL
MOVE P2,[POINT 6,T1] ;POINT AT STRING
C6T8L: ILDB T3,P2 ;GET A "DIGIT"
IMULI P1,10 ;MAKE ROOM FOR NEXT DIGIT
ADDI P1,-'0'(T3) ;MERGE IN NEW DIGIT
IMULI M1,10 ;MAKE ROOM FOR NEXT WILDCARD
CAIN T3,'?' ;SKIP IF NOT WILDCARD
JRST C6T8W ;BRANCH IF WILD
CAIL T3,'0' ;SKIP IF ILLEGAL
CAILE T3,'7' ;SKIP IF ENTIRELY LEGAL
POPJ P, ;RETURN THE ERROR TO CALLER
TRO M1,7 ;SET NOT WILD
C6T8W: SOJG T4,C6T8L ;LOOP FOR ALL DIGITS
C6T8Z: MOVE T1,P1 ;COPY RESULT
MOVE T2,P3 ;INSERT CHARACTER COUNT
MOVE T3,LASTCH ;RESTORE THE TERMINATOR
JRST CPOPJ1 ;GIVE GOOD RETURN
;ROUTINE TO CONVERT T1 V M1 OCTAL INTO T1 V M1 SIXBIT
MAKUIC: MOVSS T1 ;SWAP HALVES
DPB T1,[POINT 9,T1,8] ;MAKE LH T1=ALL OF T1
MOVSS M1
DPB M1,[POINT 9,M1,8]
SETZB T2,M2 ;GET READY
MOVEI T3,6
MAKUI1: LSH T2,3 ;MAKE ROOM FOR NEXT DIGIT
LSH M2,6 ;MAKE ROOM FOR NEXT WILDCARD
ROTC T1,3 ;GET NEXT DIGIT INTO T2
ROT M1,3 ;GET NEXT ? INTO 0-5 OF M1
TRO T2,'0' ;CONVERT T2 INTO SIXBIT
SKIPGE M1 ;SKIP IF NO NEED TO PROPOGATE
TRO M2,77 ;PROPOGATE NONZERO WILDCARD ATOM
SOJG T3,MAKUI1 ;LOOP FOR ALL OF THEM
MOVE T1,T2
MOVE M1,M2
POPJ P,
;ROUTINE TO SKIP IF LAST CHARACTER WAS A TERMINATOR
TRMSKP: MOVE T3,LASTCH
TRMSK0: CAIE T3,12
CAIN T3,13
JRST CPOPJ1
CAIE T3,14
CAIN T3,33
JRST CPOPJ1
CAIN T3,32
CPOPJ1: AOS (P)
CPOPJ: POPJ P,0
FNDIDX: MOVE U0,@(P) ;PICK UP THE CAIA
PUSHJ P,SAVE4 ;SAVE SOME ACS
JUMPE T2,FNDID0 ;MULTI-WORD SIXBIT COMMAND/SWITCH?
SETZ T2, ;CAN'T HANDLE THAT
MOVEI T4,6 ;TRIM DOWN TO SIX CHARACTERS
FNDID0: MOVE P3,U0 ;MAKE A SAFER COPY
SETZ P4, ;NOTHING SEEN YET
FNDID1: MOVE P1,(U0) ;PICK UP A POSSIBLE
JUMPE P1,FNDID4 ;DONE WITH POSSIILITIES LIST
AND P1,MASKS(T4) ;CHOP OFF EXCESS CHARACTERS
CAME P1,T1 ;CHECK FOR MATCH
AOJA U0,FNDID1 ;TRY FOR OTHER MATCHES
JUMPN P4,FNDID3 ;BRANCH IF TOO MANY MATCHES
MOVE P4,U0 ;REMEMBER MATCH POINTER FOR LATER
AOJA U0,FNDID1 ;LOOP FOR MORE
FNDID3: SETO T1, ;MARK ILLEGAL
POPJ P, ;RETURN
FNDID4: JUMPE P4,FNDID5 ;BRANCH IF NEVER FOUND ONE
MOVE T1,P4 ;COPY MATCHING MARK
SUB T1,P3 ;COMPUTE OFFSET
POPJ P,
FNDID5: HRROI T1,-2 ;MARK NO MATCH
POPJ P, ;RETURN
MASKS: 0 ;0
770000,,000000 ;1
777700,,000000 ;2
777777,,000000 ;3
777777,,770000 ;4
777777,,777700 ;5
777777,,777777 ;6
SUBTTL VARIOUS SAVING CO-ROUTINES
SAVFF: PUSH P,.JBFF## ;SAVE CURRENT CORE BOUNDS
PUSHJ P,@-1(P) ;CALL CALLER
SKIPA
AOS -2(P)
POP P,.JBFF## ;RESTORE CORE BOUND POINTER
PUSH P,T1 ;SAVE AN AC
HRRZ T1,.JBFF## ;GET UPPER LIMIT
IORI T1,777 ;ROUND TO NEAREST PAGE
CAMLE T1,.JBREL## ;ALREADY BELOW THAT?
CORE T1, ;NO, SHRINK CORE
JFCL
POP P,T1
POP P,(P)
POPJ P, ;RETURN TO CALLER'S CALLER
SAVE1: PUSH P,P1 ;SAVE P1
PUSHJ P,@-1(P) ;CALL CALLER AS A SUBROUTINE
SKIPA
AOS -2(P) ;PROPOGATE SKIP RETURN
POP P,P1
POP P,(P) ;WASTE CALLER'S ADDRESS
POPJ P,
SAVE2: PUSH P,P1 ;SAVE P1
PUSH P,P2 ;SAVE P2
PUSHJ P,@-2(P) ;CALL CALLER AS A SUBROUTINE
SKIPA
AOS -3(P) ;PROPOGATE THE SKIP RETURN
POP P,P2
POP P,P1
POP P,(P)
POPJ P,
SAVE4: PUSH P,P1
PUSH P,P2
PUSH P,P3
PUSH P,P4
PUSHJ P,@-4(P)
SKIPA
AOS -5(P)
POP P,P4
POP P,P3
POP P,P2
POP P,P1
POP P,(P)
POPJ P,
SAVFP: PUSH P,FP
PUSHJ P,@-1(P)
SKIPA
AOS -2(P)
POP P,FP
POP P,(P)
POPJ P,
SUBTTL GETCOR
; ROUTINE TO RETURN A NEWLY ALLOCATED CHUNK OF CORE
GETCOR: PUSHJ P,SAVE2 ;SAVE SOME ACS
MOVE P1,.JBFF## ;PRESERVE ORIGINAL VALUE
ADDB T1,.JBFF## ;UPDATE TO NEWEST ADDRESS
CAMG T1,.JBREL## ;SKIP IF WE MUST EXPAND
JRST GETCO1 ;BRANCH
CORE T1, ;EXPAND OUR IMAGE
ERROR <CANNOT EXPAND CORE>
GETCO1: MOVE T1,P1 ;GET RETURN VALUE
POPJ P, ;RETURN
SUBTTL DO THE GETTABS
DEFINE GET(.a,.b),< MOVE T1,[.a]
GETTAB T1,
SETZ T1,
MOVEM T1,.b>
DOGETS: GET %CNYER,LOCYER
GET %CNMON,LOCMON
GET %CNDAY,LOCDAY
GET %CNHOR,LOCHOR
GET %CNMIN,LOCMIN
GET %CNSEC,LOCSEC
POPJ P,0
; ROUTINE TO POSITION DISK FOR I/O
SUSET: SKIPE FAKVOL
JRST LSUSET
MOVEM T1,LASSET
TLO T1,(<Z VIO,0>!SU.SOT)
SUSET. T1,
ERROR <SUSET. failed>
POPJ P,0
LSUSET: MOVEM T1,LASSET
ADD T1,FAKOFS
USETI VIO,1(T1)
STATZ VIO,IO.IMP
ERROR <USETI failed>
; USETO VIO,1(T1)
; STATZ VIO,IO.IMP
; ERROR <USETO failed>
JFCL ;LET THIS GET CAUGHT WHEN WE TRY THE OUT UUO
SUB T1,FAKOFS
POPJ P,
; ROUTINE TO TYPE A STRING
;
; PUSHJ P,TYPE..
; CAI [asciz .string.]
TYPE..: HRRZM P,SAVEP ;SAVE P A SECOND
PUSHJ P,SAVE4 ;GET SOME ACS
MOVE P1,SAVEP ;GET THE CAI INSTRUCTION
MOVE P1,@(P1) ;..
HRLI P1,(POINT 7,0) ;MAKE A BYTE POINTER
TYPE.1: ILDB T3,P1 ;GET A BYTE
JUMPE T3,CPOPJ ;RETURN
PUSHJ P,TYO ;TYPE THE BYTE
JRST TYPE.1 ;LOOP TILL END
; ROUTINE TO TYPE A CHARACTER
TYO: PUSH P,T1
MOVEI T1,TTY
DEVNAM T1,
JFCL
AOJGE T1,[POP P,T1
OUTCHR T3
POPJ P,]
POP P,T1
SOSG TTYOBF+.BFCTR ;ROOM?
JRST TYO2 ;NO, MAKE ROOM
PUSHJ P,ADJCOL ;FIXUP THE COLUMN
IDPB T3,TTYOBF+.BFPTR;YES, PUT IN BYTE
TDNE F,[X%INT] ;INTERACTIVE DEVICE? (TTY:)
CAIE T3,12 ;YES, AND LINE FEED?
POPJ P, ;RETURN
OUT TTY, ;OUTPUT BUFFER
POPJ P,0
JRST TYO3 ;ERROR
TYO2: OUT TTY, ;WRITE OUT A BLOCK
JRST TYO
TYO3: ERROR <OUT failed to TTY:>
; ROUTINE TO PUT A CHARACTER INTO THE OUTPUT FILE
PUTC: JUMPE T3,CPOPJ ;IGNORE NULLS
XPUTC: SOSGE DOBUF+.BFCTR ;ROOM?
JRST PUTC2 ;NO, MAKE ROOM
AOS PUTCTR ;COUNT IT
IDPB T3,DOBUF+.BFPTR ;PUT IN BYTE
POPJ P,0
PUTC2: OUT FIO,
JRST PUTC ;RETY AGAIN
PUSHJ P,G$OER ;REPORT ERROR AND FIX STATUS
POPJ P, ;THEN JUST IGNORE THE ERROR
; ROUTINE TO ENSURE THE COLUME COUNTER IS ALWAYS CORRECT
; LEFT MARGIN IS COLUMN 0, NOT COLUMN 1
ADJCOL: JUMPE T3,CPOPJ
CAIN T3,15 ;CR?
JRST [SETZM COLUMN ;YES, WE'RE IN COLUM 0
POPJ P,] ;YES, WE'RE DONE
CAIE T3,14 ;FF
CAIN T3,12 ;OR LF?
POPJ P, ;YES, THAT DOESN'T CHANGE COLUME
CAIE T3,11 ;TAB?
JRST [AOS COLUMN ;NO, BUMP COLUMN BY ONE
POPJ P,] ;THEN EXIT
EXCH T3,COLUMN ;EXCHANGE COLUMN
TRO T3,7
ADDI T3,1
EXCH T3,COLUMN
POPJ P,
; ROUTINE TO MOVE THE CURSOR TO THE CORRECT COLUMN
MOVCOL: PUSHJ P,SAVE2 ;SAVE SOME ACS
MOVCO1: MOVE P1,COLUMN ;GET CURRENT COLUMN
TRO P1,7
ADDI P1,1
CAMG P1,T1 ;IF WE TABBED NOW, SKIP IF TOO MUCH
JRST [TYPE < > ;NO, SO DO THE TAB
JRST MOVCO1] ;NO, SO TRY AGAIN AFTER TAB'ING
MOVCO2: MOVE P1,COLUMN ;GET CURRENT COLUMN
CAML P1,T1 ;ARE WE FAR ENOUGH YET?
POPJ P, ;YES, WE'RE DONE
TYPE < > ;NO, MOVE ONE COLUMN RIGHT
JRST MOVCO2 ;AND CHECK AGAIN
; ROUTINE TO TYPE THE REVISION DTM
TYPRDT: PUSHJ P,SAVE1 ;SAVE SOME ACS
MOVE P1,T1 ;COPY
SUBI P1,FHBBUF
IMULI P1,4
LOAD. T1,RDAy,P1
JUMPE T1,CPOPJ
MOVEi T1,^D56
PUSHJ P,MOVCOL
MOVE T1,[XWD O.RVDT,A.RVDT]
PUSHJ P,TYPDAT
TYPE < >
MOVE T1,[XWD O.RVTI,A.RVTI]
PJRST TYPTIM
; ROUTINE TO TYPE THE CREATION DTM
TYPCDT: PUSHJ P,SAVE1
MOVE P1,T1
SUBI P1,FHBBUF
IMULI P1,4
LOAD. T1,CDAy,P1
JUMPE T1,CPOPJ
MOVEI T1,^D40
PUSHJ P,MOVCOL
MOVE T1,[XWD O.CRDT,A.CRDT]
PUSHJ P,TYPDAT
TYPE < >
MOVE T1,[XWD O.CRTI,A.CRTI]
PJRST TYPTIM
; ROUTINE TO TYPE THE EXPIRATION DTM
TYPXDT: MOVE P1,T1
SUBI P1,FHBBUF
IMULI P1,4
LOAD. T1,XDAy,p1
JUMPE T1,CPOPJ
MOVEI T1,^D72
PUSHJ P,MOVCOL
MOVE T1,[XWD O.EXDT,A.EXDT]
PJRST TYPDAT
;ROUTINE TO TYPE THE PDP11 DATE
;
; CALL WITH T1/ PDP11 BYTE POINTER
; P1/ OFFSET POINTER AT BLOCK CONTAINING THE DATE
TYPDAT: MOVSS T1 ;GET BYTE OFFSET PART INTO RH OF T1
ADDI T1,(P1) ;COMPUTE FINAL BYTE POINTER
MOVSS T1 ;TURN T1 BACK INTO PDP11 BYTE POINTER
JSR GETBYT ;GET 1ST DIGIT OF "DD"
ANDI T3,177 ;CONVERT TO PDP10
CAIN T3,"0" ;SKIP IF NOT A LEADING ZERO IN "DD"
MOVEI T3," " ;CONVERT LEADING ZERO TO A BLANK
PUSHJ P,TYO ;TYPE 1ST "D" OF "DD"
PUSHJ P,TYPBYT ;TYPE 2ND "D" OF "DD"
TYPE <-> ;TYPE SEPERATOR TO HERALD THE MONTH
PUSHJ P,TYPBYT ;TYPE 1ST "M" OF "MMM"
JSR GETBYT ;GET 2ND LETTER
ANDI T3,177 ;TRIM TO 7 BIT ASCII
CAIGE T3,"a" ;SKIP IF LOWER CASE
ADDI T3,40 ;CONVERT TO LOWER CASE IF UPPER
PUSHJ P,TYO ;TYPE 2ND "M" OF "MMM"
JSR GETBYT ;GET 3RD "M" OF "MMM"
ANDI T3,177 ;TRIM TO 7 BIT ASCII
CAIGE T3,"a" ;SKIP IF ALREADY LOWER CASE
ADDI T3,40 ;CONVERT TO LOWER CASE
PUSHJ P,TYO ;TYPE 3RD "M" OF "MMM"
TYPE <-> ;TYPE SEPERATOR FOR YEAR
PUSHJ P,TYPBYT ;GET AND TYPE 1ST "Y" OF "YY"
PJRST TYPBYT ;GET AND TYPE 2ND "Y" OF "YY"
;ROUTINE TO TYPE PDP11 TIME
;
; CALL WITH T1/ PDP11 BYTE POINTER
; P1/ OFFSET INTO CORRECT BLOCK WITH TIME
TYPTIM: MOVSS T1 ;GET BYTE OFFSET PART INTO RH OF T1
ADDI T1,(P1) ;COMPUTE FINAL ADDRESS OF STRING
MOVSS T1 ;TURN T1 BACK INTO PDP11 BYTE POINTER
PUSHJ P,TYPTI2 ;GO TYPE 2 DIGITS OF TIME
TYPE <:> ;SEPERATE
;ROUTINE TO TYPE 2 DIGITS FROM PDP11 BYTE POINTER
TYPTI2: PUSHJ P,TYPBYT ;GET AND TYPE A DIGIT
;ROUTINE TO GET AND TYPE A PDP11 BYTE
TYPBYT: JSR GETBYT ;GET THE BYTE TO TYPE
JRST TYO ;TYPE IT
; ROUTINE TO READ A PDP11 TIME AND LOAD T1=PDP10 "MINUTES PAST MIDNITE"
;
; T1/ PDP11 BYTE POINTER
; T2/ FHB TO READ FROM
REDTIM: PUSHJ P,SAVE4 ;SAVE SOME ACS
DMOVE P1,T1 ;COPY THE INPUT ARGS
SUBI P2,FHBBUF ;RELOCATE
ADD T1,P2 ;...THE BYTE POINTER
JSR GETBYT ;GET 1ST DIGIT OF HOURS
CAIN T3," " ;IF IT IS A LEADING BLANK
MOVEI T3,"0" ;...CONVERT TO LEADING 0
MOVEI P4,-"0"(T3) ;P4=1ST DIGIT OF HOUR
JSR GETBYT ;GET 2ND DIGIT OF HOURS
IMULI P4,^D10
ADDI P4,-"0"(T3) ;NOW P4=HOURS
IMULI P4,^D60 ;NOW P4=MINS IN THE HOURS PAST MIDNITE
JSR GETBYT ;GET 1ST DIGIT OF MINUTES
MOVEI P3,-"0"(T3) ;CONVERT TO A NUMBER
JSR GETBYT ;GET 2ND DIGIT OF MINUTES
IMULI P3,^D10 ;MAKE ROOM FOR 2ND DIGIT
ADDI P3,-"0"(T3) ;COMBINE TO MAKE ACTUAL 2 DIGIT NUMBER
MOVE T1,P4 ;COPY NUMBER OF MINS TO T1
ADD T1,P3 ;ADD IN HOUR'S MINUTES
POPJ P,
; ROUTINE TO STORE A PDP11 TIME FIELD INTO FHB FROM T1/PDP10 MINUTES PAST MIDNITE
;
; T1/ PDP11 BYTE POINTER
; T2/ FHB TO STORE INTO
; T3/ MINUTES PAST MIDNITE
STOTIM: PUSHJ P,SAVE4 ;SAVE SOME ACS
DMOVE P1,T1 ;COPY THE INPUT ARGS
MOVE P3,T3 ;COPY...
SUBI T2,FHBBUF ;OFFSET THE FHB BUFFER
ADD T1,T2 ;COMPUTE ACTUAL FIELD'S BYTE POINTER
IDIVI P3,^D60 ;NOW P3=HOURS, P4=MINUTES
MOVE T3,P3 ;COPY HOURS
IDIVI T3,^D10 ;SEPERATE INTO DIGITS
MOVEI T3,"0"(T3) ;CONVERT TO ASCII
; CAIN T3,"0" ;SKIP IF 1ST DIGIT IS NOT A LEADING ZERO
; MOVEI T3," " ;CONVERT LEADING ZERO INTO A BLANK
JSR PUTBYT ;INSERT LEADING DIGIT
MOVEI T3,"0"(T4) ;T3=REMAINDER'S DIGIT IN ASCII
JSR PUTBYT ;INSERT TRAILING DIGIT
MOVE T3,P4 ;COPY T3=MINUTES
IDIVI T3,^D10 ;NOW T3=10'S, T4=1'S OF MINUTES
MOVEI T3,"0"(T3) ;CONVERT 10'S TO ASCII DIGIT
JSR PUTBYT ;INSERT 1ST DIGIT OF MINUTES
MOVEI T3,"0"(T4) ;ASCII-IZE 2ND DIGIT
JSR PUTBYT ;INSERT 2ND DIGIT OF MINUTES
MOVEI T3,"0" ;GET AN ASCII ZERO
JSR PUTBYT ;SIMPLIFY LIFE BY CLAIMING SECONDS=00
JSR PUTBYT ;...SO INSERT 2 ASCII 0'S
POPJ P,
; ROUTINE TO READ A PDP11 DATE AND LOAD T1=15 BIT PDP10 DATE
;
; T1/ PDP11 BYTE POINTER
; T2/ FHB TO READ FROM
REDDAT: PUSHJ P,SAVE4 ;SAVE SOME ACS
DMOVE P1,T1 ;COPY THE INPUT ARGS
ADDI T1,-FHBBUF(P2)
SETZ P4, ;P4=TEMP FOR GETTING DATE
JSR GETBYT ;GET A BYTE
CAIN T3," " ;IS IT A LEADING BLANK?
MOVEI T3,"0" ;YES, CHANGE IT TO A LEADING 0
MOVEI P4,-"0"(T3) ;GET 10'S DIGIT OF DAY IN MONTH
JSR GETBYT ;GET 2ND DIGIT OF DATE
IMULI P4,^D10
ADDI P4,-"0"(T3) ;NOW, P4=DD OF DDMMMYY
JSR GETBYT ;GET 1ST LETTER OF MONTH
HRLZ P3,T3 ;INSERT 1ST LETTER
JSR GETBYT ;GET 2ND LETTER OF MONTH
CAIL T3,"a" ;SKIP IF NOT LOWER CASE
CAILE T3,"z" ;SKIP IF DEFINATELY LOWER CASE
SKIPA ;SKIP IF NOT LOWER CASE
SUBI T3,"a"-"A" ;CONVERT TO UPPER CASE IF LOWER
DPB T3,[POINT 8,P3,9] ;INSERT 2ND LETTER
JSR GETBYT ;GET 3RD LETTER OF MONTH
CAIL T3,"a" ;SKIP IF NOT LOWER CASE
CAILE T3,"z" ;SKIP IF DEFINATELY LOWER CASE
SKIPA ;SKIP IF NOT LOWER CASE
SUBI T3,"a"-"A" ;CONVERT TO UPPER CASE IF LOWER
HRRI P3,(T3) ;AND INSERT IT
JSR GETBYT ;GET 1ST BYTE OF YEAR
MOVEI P2,-"0"(T3) ;PUT 1ST BYTE INTO P2
JSR GETBYT ;GET 2ND BYTE OF YEAR
IMULI P2,^D10 ;
ADDI P2,-"0"(T3) ;P2=LAST 2 DIGITS OF YEAR
MOVSI P1,^D-12 ;AOBJN INTO LEGAL MONTHS TABLE
CAME P3,MONTAB(P1) ;SKIP IF WE FOUND IT
AOBJN P1,.-1 ;KEEP LOOKING
JUMPGE P1,[TYPE <% Illegal month in input string
>
setz t1,
popj p,]
MOVEI T1,^D1900-^D1964(P2) ;GET THE YEAR IN DESIRED FORMAT
IMULI T1,^D12
ADDI T1,(P1) ;ADD MONTH-1
IMULI T1,^D31 ;
ADDI T1,-1(P4)
POPJ P,
; ROUTINE TO STORE A 15 BIT PDP10 DATE IN (T3) INTO A PDP11 ASCII FIELD
;
; T1/ PDP11 BYTE POINTER
; T2/ FHB TO STORE INTO
; T3/ 15 BIT DATE
STODAT: PUSHJ P,SAVE4
DMOVE P1,T1 ;COPY T1, T2
DMOVE P3,T3 ;COPY T3, T4
SUBI P2,FHBBUF ;COMPUTE OFFSET INTO REAL FHB
ADD T1,P2 ;COMPUTE FINAL BYTE POINTER
MOVE P2,P3 ;COPY DATE INTO BETTER AC
IDIVI P2,^D31 ;GET P2=YEAR,MONTH, P3=DAY-1
ADDI P3,1 ;COMPUTE P3=DAY+0
IDIVI P3,^D10 ;P3=1ST DIGIT IN DAY, P4=2ND DIGIT
MOVEI T3,"0"(P3) ;GET FIRST DIGIT
; CAIN T3,"0" ;
; MOVEI T3," " ;CONVERT 1ST DIGIT TO BLANK IF 0
JSR PUTBYT ;STORE IT
MOVEI T3,"0"(P4) ;COPY 2ND DIGIT
JSR PUTBYT ;STORE 2ND DIGIT
IDIVI P2,^D12 ;P2=YEAR, P3=MONTH#
LDB T3,[POINT 8,MONTAB(P3),17];GET 1ST LETTER OF MONTH
JSR PUTBYT ;STORE 1ST LETTER
LDB T3,[POINT 8,MONTAB(P3),9];GET 2ND LETTER OF MONTH
JSR PUTBYT ;STORE 2ND LETTER
HRRZ T3,MONTAB(P3) ;GET 3RD LETTER
JSR PUTBYT ;STORE 3RD LETTER
ADDI P2,^D1964-^D1900
IDIVI P2,^D10
MOVEI T3,"0"(P2)
JSR PUTBYT
MOVEI T3,"0"(P3)
JSR PUTBYT
POPJ P,
; ROUTINE TO MOVE A PDP11 FIELD
;
; JSP U0,MOV..
; CAI ORIGIN FIELD, ALWAYS JUSTIFIED "NORMALLY"
; CAI DESTINATION BASE ADDRESS
; CAI #PDP11 BYTES OFFSET FROM DESTINATION BASE
; CAI #BYTES IN FIELD TO MOVE
; CAI ADDRESS OF AN ADDITIONAL OFFSET
MOV..: PUSHJ P,SAVACS ;SAVE THE ACS
MOVE P1,0(U0) ;PICK UP ADDRESS OF ORIGIN FIELD
TLZ P1,777000 ;TURN OF CAI
TLO P1,(MOVEI P1,0) ;TURN ON MOVEI
MOVEM P1,P1XCT ;SAVE IT
MOVE P1,SAVAC0+P1 ;RESTORE ORIGINAL P1
XCT P1XCT ;LOAD THE ADDRESS INTO P1
CAIG P1,17 ;ORIGIN IN THE ACS?
ADDI P1,SAVAC0 ;YES, POINT AT SAVED COPY
HRRZ P2,2(U0) ;GET # OF BYTES
DMOVEM P1,MOV.P1 ;SAVE P1, P2
DMOVE P1,SAVAC0+P1 ;RESTORE P1, P2
PUSH P,@4(U0) ;SAVE ADDITIONAL BYTES ON STACK
DMOVE P1,MOV.P1 ;GET BACK P1, P2
POP P,MOV.P1 ;GET BACK ADDITIONAL BYTES
ADD P2,MOV.P1 ;ADD IN ADDITIONAL BYTES
HRLZS P2 ;PUT INTO LH HALF
HRR P2,1(U0) ;INSERT ADDRESS OF DESTINATION FIELD
HRRZ T1,1(u0) ;GET DESTINATION BASE
CAIG T1,17
ADDI P2,SAVAC0 ;RELOCATE IT IF IN THE ACS
HRRZ P3,3(U0) ;P3=# OF BYTES TO MOVE
;P2=POINTER TO DESTINATION BYTE
;P1=POINTER TO ORIGIN BYTE
MOV.1: MOVE T1,P1 ;COPY BYTE POINTER
JSR GETBYT ;GET A BYTE @P1
MOVEM T1,P1 ;PUT BYTE POINTER BACK
MOVE T1,P2 ;GET BYTE POINTER
JSR PUTBYT ;PUT A BYTE @P2
MOVEM T1,P2 ;PUT BYTE POINTER BACK
SOJG P3,MOV.1 ;LOOP FOR ALL BYTES TO BE MOVED
PUSHJ P,RESACS ;RESTORE ACS
POPJ P,0
; ROUTINE TO STORE A PDP10 FORMATTED FIELD INTO A PDP11 FIELD
;
; JSP U0,STOR..
; CAI ORIGIN VALUE
; CAI DESTINATION BASE ADDRESS
; CAI #PDP11 BYTES OFFSET FROM DESTINATION BASE
; CAI #BYTES IN FIELD TO MOVE
; CAI ADDRESS OF ADDITION OFFSET
STOR..: PUSHJ P,SAVACS ;SAVE THE ACS
MOVE T3,@0(U0) ;PICK UP VALUE TO STORE
HRRZ T1,2(U0) ;GET # OF BYTES IN OFFSET
ADD T1,@4(U0) ;ADD ADDITIONAL BYTES
MOVSI T1,(T1) ;FORM PDP11 BYTE POINTER
HRR T1,1(U0) ;INSERT BASE ADDRESS
HRRZ T2,1(u0) ;GET BASE DESTINATION
CAIG T2,17
ADDI T1,SAVAC0 ;RELOCATE IT IN GOING TO ACS
HRRZ P3,3(U0) ;GET SIZE OF FIELD
STOR.1: JSR PUTBYT ;STORE A BYTE
LSH T3,-^D8 ;POSITION TO NEXT BYTE
SOJG P3,STOR.1 ;LOOP TILL PDP10 FIELD COPIED
PUSHJ P,RESACS ;RESTORE ACS
POPJ P,0 ;DONE
; ROUTINE TO XFER A PDP11 FORMATTED FIELD TO A PDP10 FIELD
;
; PUSHJ P,[JSP U0,LOAD..
; CAI ORIGIN
; CAI A.DEST
; CAI O.DEST
; CAI S.DEST
; CAI OFFSET
LOAD..: PUSHJ P,SAVACS ;SAVE THE ACS
HRRZ T1,@4(U0) ;GET ADDITIONAL OFFSET FIRST
ADD T1,2(U0) ;ADD IN BASE OFFSET
MOVSI T1,(T1) ;CREATE PDP11 BYTE POINTER
HRR T1,1(U0) ;INSERT ADDRESS
SETZ P2, ;START PDP10 FIELD OFF AT ZEROES
HRRZ P3,3(U0) ;GET LENGTH OF XFER IN BYTES
LOAD.1: LSH P2,-^D8 ;MAKE ROOM FOR ANOTHER
JSR GETBYT ;GET A PDP11 BYTE
DPB T3,[POINT 8,P2,7] ;MERGE WITH PDP10 DATA
SOJG P3,LOAD.1 ;LOOP FOR ALL BYTES
HRRZ P3,3(U0) ;GET SIZE OF FIELD IN BYTES
MOVN P3,[0
^D36-^D8
^D36-^D16
^D36-^D24
^D36-^D32](P3)
LSH P2,(P3) ;RIGHT JUSTIFY IT
MOVEI T1,@0(u0) ;COMPUTE DESTINATION ADDRESS
CAIG T1,17
ADDI T1,SAVAC0
MOVEM P2,(T1) ;STORE FIELD
PUSHJ P,RESACS ;RESTORE THE ACS
POPJ P, ;RETURN
; ROUTINE TO SAVE THE ACS
SAVACS: MOVEM 17,SAVAC0+17
MOVEI 17,SAVAC0
BLT 17,SAVAC0+16
MOVE 17,SAVAC0+17
POPJ P,
RESACS: MOVEM P,SAVEP
MOVSI 17,SAVAC0
BLT 17,17
MOVE P,SAVEp
POPJ P,
SUBTTL IMPURE
RELOC LOWSEG ;LOWSEG
; ROUTINE TO STORE A PDP11 BYTE
;ENTER: T1/ PDP11 BYTE POINTER, T3/ BYTE TO STORE
;EXIT: T1/ UPDATED BYTE POINTER
PUTBYT: 0 ;RETURN PC SETUP BY JSR
DMOVEM P1,QS2A ;SAVE SOME ACS
HLRZ P1,T1 ;COPY THE OFFSET
IDIVI P1,4 ;CONVERT TO WORD#, BYTE#
ADDI P1,(T1) ;ADD IN BASE ADDRESS
DPB T3,[POINT 8,(P1),17
POINT 8,(P1),9
POINT 8,(P1),35
POINT 8,(P1),27](P2)
ADD T1,[1,,0] ;UPDATE POINTER
DMOVE P1,QS2A ;RESTORE SOME ACS
JRST @PUTBYT ;RETURN
; ROUTINE TO GET A PDP11 BYTE
;ENTER: T1/ PDP11 BYTE POINTER
;EXIT: T1/ UPDATED PDP11 BYTE POINTER, T3=FETCHED BYTE
GETBYT: 0 ;RETURN PC SETUP BY JSR
DMOVEM P1,QS2A ;SAVE SOME ACS
HLRZ P1,T1 ;GET ONLY THE OFFSET PORTION
IDIVI P1,4 ;CONVERT TO WORD#, BYTE#
ADDI P1,(T1) ;ADD IN THE BASE ADDRESS
LDB T3,[POINT 8,(P1),17
POINT 8,(P1),9
POINT 8,(P1),35
POINT 8,(P1),27](P2)
ADD T1,[1,,0] ;STEP TO NEXT BYTE
DMOVE P1,QS2A ;RESTORE SOME ACS
JRST @GETBYT ;RETURN
STOLFT: BLOCK 1 ;# BLOCKS LEFT IN THIS POINTER
CHULFT: BLOCK 1 ;# BLOCKS LEFT IN THIS CHUNK
STOCNT: BLOCK 1 ;ACTUAL # OF BLOCKS IN THIS POINTER
STOLBN: BLOCK 1 ;LBN OF FIRST BLOCK IN THIS POINTER
CHULBN: BLOCK 1 ;LBN OF FIRST BLOCK IN THIS CHUNK
QS2A: BLOCK 2 ;P1/P2 SAVE FOR PUTBYT
TMPOFF: BLOCK 1 ;
LASSET: BLOCK 1 ;LAST BLOCK NUMBER SUSET'D TO
REQALC: BLOCK 1 ;REQUIRED ALLOCATION DURING A CREATE
FAKVOL: BLOCK 1 ;FLAG THAT WE'RE REFERENCING A LOGICAL VOLUME
FAKOFS: BLOCK 1
VOLTBL: BLOCK VOLMAX ;NAME TABLE
DEFINE VF(A),<VOLF'A:BLOCK .FXLEN>
A==0
XLIST ;THE VOLUME FDB'S
REPEAT VOLMAX,<
VF \A
A==A+1>
LIST
CLUSIZ: BLOCK 1 ;CLUSTER SIZE
HIHIGH: BLOCK 1
LASTHI: BLOCK 1
PFLAG: BLOCK 1
BYTNUM: BLOCK 1 ;USED TO EXTRACT BYTES DURING BOOT COMMAND
BOTCNT: block 1 ;BYTE COUNT USED DURING BOOT COMMAND
BOTPTR: block 1 ;BYTE POINTER USED DURING BOOT COMMAND
BOTDAT: block 200 ;BUFFER USED DURING BOOT COMMAND
BOTBLK==20 ;ALLOW BOOT TO WRITE ONTO BLOCKS 0-17
BOTBUF: BLOCK BOTBLK*200
CHKVAL: BLOCK 1 ;CHECKSUM VALUE DURING BOOT COMMAND
LBC: BLOCK 1 ;BYTE COUNT FROM BIN FILE RECORD
LINNUM: BLOCK 1 ;LINE NUMBER ON A LINE FROM LINE NUMBERED FILE
BLKCNT: BLOCK 1 ;
LINSIZ: BLOCK 1 ;BIGGEST LINE SIZE IN TEXT CHARACTERS
LINBUF: BLOCK 1000 ;BUFFER FOR A LINE FROM FILE
FHBFOO: BLOCK 1
FPCOPY: BLOCK 1
IDXBLK: BLOCK 1 ;USED BY /INDEX:BLK:NNN
LOWZRO: BLOCK 1 ;VALUE IN LOWSEG GUARENTEED TO BE 0
MOV.P1::BLOCK 2 ;2 TEMPS USED BY MOV..
P1XCT: BLOCK 1 ;TEMP USED BY MOV.., STOR.., ETC...
.MYPPN::BLOCK 0 ;MAKE PPN AVAILABLE TO SCAN
MYPPN:: BLOCK 1 ;LOGGED IN PPN
FPWILD: BLOCK 1 ;USED BY WILD TO REMEMBER CONTEXT ACROSS CALLS
IPLIST: BLOCK 1 ;POINTER TO LIST OF INPUT FILES
IPLAST: BLOCK 1 ;POINTER TO PREVIOUS INPUT FILE
CCLFLG::BLOCK 1 ;0 IF NO CCL ENTRY, -1 IF CCL'ED
RSXPTR: BLOCK 1 ;GETTER/PUTTER FOR DEALING WITH 20F FILES
RSXVBN: BLOCK 1 ;BLOCK# INSIDE 20F FILE (IE: "USETI" VALUE)
FFBYTE: BLOCK 1 ;BYTE WHICH IS THE "FIRST FREE" (IE: THE EOF BYTE)
RSXCTR: BLOCK 1 ;GETTER COUNT/PUTTER COUNT FOR DEALING WITH 20F FILES
PUTCTR: BLOCK 1 ;...
SAVEP: BLOCK 1
SAVAC0: BLOCK 20
COLUMN: BLOCK 1
PTHLEN==20
PTHBLK: BLOCK PTHLEN
TOTBLK: BLOCK 1
TOTFIL: BLOCK 1
UFDNAM: BLOCK 1
UF2NAM: BLOCK 1
MOD16: BLOCK 1
STATIC: BLOCK .FXLEN
OUTFDB: BLOCK .FXLEN
INPFDB: BLOCK .FXLEN
TMPFDB: BLOCK .FXLEN
DELFDB: BLOCK .FXLEN
UFDFDB: BLOCK .FXLEN
FAKFDB: BLOCK .FXLEN
NULFDB: BLOCK .FXLEN
DEFFDB: BLOCK .FXLEN
;
; ** FHBBUF MUST FALL PHYSICALLY BEFORE ANY OTHER BUFFER
; ** WHICH GETS USED TO HOLD AN FHB, OTHERWISE THE LOAD./STORE.
; ** MACROS WILL NOT WORK WITH THE "ADDITIONAL OFFSET" OPTION
FHBBUF: BLOCK 200
OPNBLK: BLOCK 4
LERBLK: BLOCK 200 ;L/E/R BLOCK
BMBUF: BLOCK 200 ;SBM BM BUFFER (IE: FUNNY SAB BLOCK)
FSTLBN: BLOCK 1 ;1ST BLOCK OF DATA IN FE.SYS
LSTLBN: BLOCK 1 ;LAST BLOCK OF DATA IN FE.SYS
LASTCH: BLOCK 1
FEUNIT: BLOCK 1
DSKBLK: BLOCK .DCUPN+1
H11LBN: BLOCK 1 ;DISK ADDRESS OF HOME BLOCK
H11BUF: BLOCK 200
BUF111: BLOCK 200 ;COPY OF FHB FOR INDEXF
BUF444: BLOCK 200 ;COPY OF FHB FOR 000000.DIR
PLEN=100
PSTAK: BLOCk PLEN
IBMSIZ: BLOCK 1 ;SIZE OF INCORE INDEX-BIT-MAP
IBMINC: BLOCK 1 ;INCORE ADDRESS OF INDEX-BIT-MAP
IBMLBN: BLOCK 1 ;INDEX-BIT-MAP DISK ADDRESS
FHBLBN: BLOCK 1 ;WHERE THE INDEX LIST STARTS
SBMSIZ: BLOCK 1 ;SIZE OF INCORE STORAGE-BIT-MAP
SBMINC: BLOCK 1 ;INCORE ADDRESS OF STORAGE-BIT-MAP
SBMLBN: BLOCK 1 ;STORAGE-BIT-MAP DISK ADDRESS
FFBLOK: BLOCK 1 ;NEXT FREE BLOCK IN ORDER
TMPBUF: BLOCK 200
HOME1: BLOCK 200
HOME2: BLOCK 200
LOCYER: BLOCK 1
LOCMON: BLOCK 1
LOCDAY: BLOCK 1
LOCHOR: BLOCK 1
LOCMIN: BLOCK 1
LOCSEC: BLOCK 1
MFDDAT: BLOCK 200
MFDLBN: BLOCK 1
FHBTAL: BLOCK 1
VOLTAL: BLOCK 1
BIG: BLOCK 1 ;SIZE OF BIGGEST SBM CHUNK
BIGP1: BLOCK 1 ;PART OF ADDRESS OF BIGGEST SBM CHUNK
BIGP2: BLOCK 1 ;2ND PART OF ADRESS OF BIGGEST SBM CHUNK
BEST: BLOCK 1 ;SIZE OF "BEST" SBM CHUNK
BESTP1: BLOCK 1 ;PART OF ADDRESS OF BEST SBM CHUNK
BESTP2: BLOCK 1 ;2ND PART OF ADDRESS
;WILD CARD STUFF
WDICNT: BLOCK 1 ;# RECORDS LEFT IN THIS BLOCK
WDIBNO: BLOCK 1 ;RELATIVE BLOK# READING DIRECTORY FILE
WDIPBN: BLOCK 1 ;PHYSICAL BLOK# FOR WDIBNO
WDIBUF: BLOCK 200 ;WILD DIRECTORY BUFFER HOLDS DIR BLOCK
WDIFHB: BLOCK 200 ;WILD DIRECTORY FHB - FHB OF DIR FILE
WDIOFF: BLOCK 1 ;OFFSET
MASCNT: BLOCK 1 ;# RECORDS LEFT IN THIS MFD BLOCK
MASBNO: BLOCK 1 ;MFD RELATIVE BLOK#
MASBUF: BLOCK 200 ;MFD BLOCK BUFFER
MASOFF: BLOCK 1 ;OFFSET
FILCNT: BLOCK 1
FILMAT: BLOCK 1
DIRMAT: BLOCK 1
DIRCNT: BLOCK 1
DIBUF: BLOCK 3
DOBUF: BLOCK 3
TTYOBF: BLOCK 3
CMDIDX: BLOCK 1 ;INDEX OF THIS COMMAND
DELBUF: BLOCK 200
UFDFHB: BLOCK 200
BLKBFR: BLOCK 200
SUBTTL PURE
RELOC ;BACK TO HISEG
; TABLE OF MONTH NAMES IN PDP11 ASCII, INDEXED BY MONTH NUMBER, 0=JAN, ETC
MONTAB: .ASCII <JAN>
.ASCII <FEB>
.ASCII <MAR>
.ASCII <APR>
.ASCII <MAY>
.ASCII <JUN>
.ASCII <JUL>
.ASCII <AUG>
.ASCII <SEP>
.ASCII <OCT>
.ASCII <NOV>
.ASCII <DEC>
; INDEX THIS TABLE BY "BIT NUMBER" AND YOU GET THE APROPRIATE MASK
B32TBL: BLOCK 0
.VAL=1B18
REPEAT ^D16,<EXP <.VAL=<.VAL*2>>>
.VAL=1B18
REPEAT ^D16,<EXP <.VAL=<.VAL*2>>_-^D18>
; THIS (TEMPORARILY) CONTAINS THE VOLUME NAME, OWNER, AND TYPE FIELDS
; WHICH GETS COPIED INTO THE FILES-11 HOME BLOCK
tmp166: 20040,,20040
20040,,20040
20040,,20040 ;volume name is 12 blanks
30133,,30460
30054,,30460
20135,,20040 ;owner name is [000,000]
42504,,43103
46111,,30505
40461,,20040 ;format type is "DECFILE11A "
; TABLE INDEXED BY RAD50 VALUE TO GIVE SIXBIT VALUE
R2STBL: BLOCK 50 ;50 SLOTS
DEFINE R2S(.arg),<IRPC .arg,<
RELOC $R.'.arg'+R2STBL
EXP ''.arg''
RELOC R2STBL+50>>
R2S <ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 $.>
; TABLE INDEXED BY SIXBIT VALUE TO GIVE RAD50 VALUE
S2RTBL: BLOCK 100 ;64 SLOTS
DEFINE S2R(.arg),<IRPC .arg,<
RELOC S2RTBL+''.arg''
EXP $R.'.arg'
RELOC S2RTBL+100>>
S2R <0123456789 $. ABCDEFGHIJKLMNOPQRSTUVWXYZ>
DEFINE VF(A),<EXP VOLF'A>
VOLPTR:
A==0
REPEAT VOLMAX,<
VF \A
A==A+1
>
LIT..: BLOCK 0
XLIST
LIT
VAR
LIST
END F11