Trailing-Edge
-
PDP-10 Archives
-
bb-jr93k-bb
-
10,7/f11/f11.mac
There are 10 other files named f11.mac in the archive. Click here to see a list.
TITLE F11 - Program to manipulate FILES-11 structures on TOPS-10 disks
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1988, 1990. 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.
VER=103
;17-Oct-89 DPM
;Incorporate bug fix from Jeff Gunter (ADP) which ensures the
;file ID in the directory for CORIMG.SYS matches the file ID in
;the FHB.
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
MOVE T1,TMPFDB+.FXNUM ;GET SELECTED (OR REQUIRED) FILE NUMBER
CAILE T1,5 ;SKIP IF KNOWN FILE (FORCE NUM=SEQ)
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