Trailing-Edge
-
PDP-10 Archives
-
BB-FP64A-SB_1986
-
10,7/f11/f11.mac
Click 10,7/f11/f11.mac to
see without markup as text/plain
There are 10 other files named f11.mac in the archive. Click here to see a list.
TITLE F11
SALL
SEARCH UUOSYM
.REQUE REL:WILD, REL:SCAN
TWOSEG
RELOC 400000
RELOC 0
LOWSEG=.
RELOC
.DIRECT FLBLST
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).
LOC <.JBVER=137>
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)
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
.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 UFX0,2 ; ALWAYS (APPARENTLY) 0
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
;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)
>
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>
MOVE T1,[S$IMAGE]
TDNE T1,.FXSWT(FP)
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
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
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
POPJ P, ;RETURN
; 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
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
DELCHK: SKIPE .FXDIR+DELFDB ;SKIP IF FILE RESIDES IN [0,0]
JRST CPOPJ1 ;GIVE GOOD RETURN IF NOT IN [0,0]
MOVE T1,.FXNUM+DELFDB ;GET FILE'S NUMBER
HLRZ T2,.FXEXT+DELFDB ;GET FILE'S TYPE
CAILE T1,4 ;SKIP IF NOT A KNOWN FILE
CAIN T2,'DIR' ;SKIP IF NOT DIRECTORY FILE
POPJ P, ;BAD RETURN IF KNOWN FILE OR DIRECTORY
CAIN T2,'NDL' ;DON'T DELETE PROTECTED FILES
POPJ P, ;
JRST CPOPJ1 ;ELSE GIVE GOOD RETURN
;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],UFX0,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
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
POPJ P, ;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,SETTTY ;SETUP TTY OUTPUT FILE IF ANY
PUSHJ P,OPNVOL ;OPEN THE VOLUME FOR I/O
PUSHJ P,RLDINI ;INITIALIZE RSX20F WILD CARD FILE
SETZM UFDOLD ;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
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: MOVE T1,UFDNAM ;GET NEW NAME
CAMN T1,UFDOLD ;NO NEED TO CHANGE ANYTHING
POPJ P, ;JUST RETURN IF NO NEED TO CHANGE
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
HLLZ T1,UFDNAM ;GET SIXBIT OF UFD'S FILE NAME
PUSHJ P,SIXOUT ;TYPE PROJECT NUMBER
TYPE <,> ;SEPERATOR
HRLZ T1,UFDNAM ;GET SIXBIT OF UFD'S PROGRAMMER NUMBER
PUSHJ P,SIXOUT ;TYPE PROGRAMMER NUMBER
TYPE <]> ;SEPERATOR
MOVE T1,UFDNAM ;GET THE NEW NAME
MOVEM T1,UFDOLD ;AND REMEMBER IT AS CURRENT
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
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
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
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
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
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: MOVE T1,.FXDIM(FP) ;GET DIRECTORY MASK
AOJN T1,ILLPPN ;BRANCH IF UIC HAD A WILD CARD
SKIPE .FXDIR+2(FP) ;SKIP IF NO SFD SPEC APPEARS IN OUTPUT FILE
JRST ILLPPN ;COMPLAIN IF OUTPUT FILE CONTAINS A SFD
MOVE T1,.FXDIR(FP) ;GET THE DIRECTORY NAME
TDNE T1,[777400,,777400];SKIP IF UIC IS OUT OF RANGE
JRST ILLPPN ;UIC MUST NOT HAVE MORE THAN 8 BITS OF #
AOJA T2,CPOPJ ;SET FLAG AND RETURN
; 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
MOVE T1,OUTFDB+.FXDIR ;GET DIRECTORY SPEC
MOVEM T1,TMPFDB+.FXDIR ;STORE IT
SETOM TMPFDB+.FXDIM ;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
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
MOVE T1,OUTFDB+.FXDIR ;GET UIC WE WANT
MOVEM T1,NULFDB+.FXDIR ;STUFF IT INTO THE NUL FDB
MOVEI T1,NULFDB ;EXPLICIT FDB OF 0S
MOVEI T2,FAKFDB ;FDB TO EXPAND INTO
PUSHJ P,NXTFDB ;FIND AN EMPTY SLOT
JRST UFDGRO ;GROW THE UFD 1 BLOCK AND TRY AGAIN
CAIN P4,177777 ;SKIP IF WE HAVEN'T RUN OUT OF VERSIONS
JRST PUTER3 ;COMPLAIN IF NO VERSION #S LEFT
AOSN P4 ;INCREMENT TO NEXT HIGHEST GENERATION
HRRZ P4,TMPFDB+.FXGEN ;GET GENERATION
ANDI P4,177777 ;ONLY KEEP LOW ORDER BITS
CAIN P4,0 ;CHECK FOR OVERFLOW
MOVEI P4,1 ;AND CONVERT TO VERSION#1 IF SO
MOVEM P4,TMPFDB+.FXGEN ;SAVE GENERATION NUMBER
MOVE T1,IPLIST ;POINT AT FIRST FILE BLOCK
MOVE T1,V$FILE(T1) ;GET /FILE SWITCH ON OUTPUT FILE
PUSHJ P,ALCFHB ;GO GET A FILE NUMBER
MOVEM T1,TMPFDB+.FXNUM ;AND REMEMBER IT FOR LATER
; HERE WHEN WE KNOW WHERE IN THE DIRECTORY WE WANT TO INSERT THIS FILE.
$PUTB3: MOVNI T1,.DIROFF ;OFFSET TO MATCHING SLOT
ADDM T1,WDIOFF ;ADJUST POINTER TO POINT AT MATCH
MOVEI T1,<TMPBUF-FHBBUF>*4 ;GET OFFSET FOR OUR FHB
MOVEM T1,FHBFOO ;SAVE IT
;NOW, "FHBFOO" IS AN OFFSET STYLE POINTER INTO THE FHB WE'RE BUILDING
;AND "WDIOFF" IS AN OFFSET POINTER INTO THE SLOT IN THE DIRECTORY WE'RE USING.
MOVE T1,TMPFDB+.FXNUM ;GET DESIRED FILE #
STOR. T1,UFNO,WDIOFF ;STORE FILE # INTO DIRECTORY
MOVEI T2,TMPBUF ;GET FHB ADDRESS
PUSHJ P,INIFHB ;CREATE THE INITIAL FHB FOR ME
LOAD. T1,RVNO,[<DELBUF-FHBBUF>*4]
TDNE F,[X%SUPER] ;SKIP IF NOT SUPERCEEDING
STOR. T1,RVNO,FHBFOO ;STORE REV # IN FHB
LOAD. T1,FSEQ,FHBFOO ;GET 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
MOVE T1,LERBLK+.RBSIZ ;GET # OF BLOCKS IN THE FILE
IDIVI T1,200 ;COMPUTE # OF BLOCKS FROM +VE WORDS
IMULI T2,4 ;NOW T2=#PDP11 BYTES
CAIE T2,0 ;SKIP IF EXACT FIT
ADDI T1,1 ;ONE MORE BLOCK IF NOT EXACT FIT
MOVEM T1,LERBLK+.RBALC ;.RBALC NOW EQUALS # OF DATA BLOCKS
MOVEM T2,LERBLK+.RBEST ;.RBEST NOW EQUALS # WORD OF SPILLAGE
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
PUSHJ P,SAVE4 ;SAVE SOME ACS
SETOB P1,P3
TDZ F,[X%EOF]
MOVEI T1,BLKBFR-1
PUSHJ P,ZAPBFR ;CLEAR TRAILING TRASH
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,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,400 ;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
MOVE T1,OUTFDB+.FXDIR ;GET PPN
PUSHJ P,PPNOUT ;TYPE IT
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
PJRST SIXOUT ;TYPE FILENAME EXTENSION
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: 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
PUSHJ P,OUT21F ;SETUP FIRST RETRIEVAL PAIR
;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 ONE BLOCK TO THE CURRENT 20F OUTPUT FILE
OUT20F: SOJL P1,OUT21F ;BRANCH IF FIRST ONE
PUSH P,T1 ;SAVE T1
PUSH P,T2 ;SAVE T2
MOVN T2,RSXCTR ;GET -VE BYTE COUNT FOR BLOCK
ADDI T2,1000 ;COMPUTE T2=BYTES USED
STOR. T2,EFBL,FHBFOO ;REMEMBER FF BYTE
HRLI T1,-200 ;CONSTRUCT 200 WORD IOWD WORD
SUBI T1,1 ;-1 FOR "DF10" FORMAT
SETZ T2, ;END IOLIST WITH 0 IOWD
OUTPUT VIO,T1 ;WRITE BLOCK OUT TO 20F VOLUME
PUSHJ P,ZAPBFR ;CLEAR BLOCK'S BUFFER FOR NEXT TIME
STATZ VIO,IO.ERR ;SKIP IF NO ERROR
JRST OUT22F ;BRANCH IF OUTPUT FAILED
POP P,T2 ;RESTORE T2
POP P,T1 ;RESTORE T1
AOS BLKCNT ;COUNT SUCCESSFULLY XFER'D BLOCK
STOR. BLKCNT,HIBL,FHBFOO ;KEEP TRACK OF HIGHEST VBN ALLOCATED
POPJ P, ;RETURN
;HERE WHEN NO MORE BLOCKS LEFT IN THIS GROUP
OUT21F: PUSH P,T1 ;SAVE BUFFER ADDRESS
PUSH P,T2 ;SAVE T2
PUSH P,T3 ;SAVE T3
DMOVE T1,P3 ;GET ORIGINAL SBM POINTERS
MOVEI T3,TMPBUF ;WHICH BUFFER TO STORETIZE
SKIPL P3 ;SKIP IF FIRST TIME
PUSHJ P,STORET ;STORE A RETRIEVAL POINTER
PUSH P,P3 ;SAVE MAGIC FLAG
SKIPGE T1,LERBLK+.RBALC ;GET # OF BLOCKS LEFT IN FILE
MOVEI T1,1 ;JUST ONE IF WE'RE BEYOND EXPECTED EOF
CAILE T1,^D256 ;SKIP IF SIZE IS OK
MOVEI T1,^D256 ;REDUCE SIZE IF TOO BIG
PUSHJ P,SCNSBM ;GO GET SOME BLOCKS
TYPE <? 20F volume out of space >,OUT23F
CAILE T1,^D256 ;TOO BIG FOR RETRIEVAL POINTER?
MOVEI T1,^D256 ;YES, TRUNCATE IT THEN
DMOVE P1,T1 ;SAVE RET APRI
DMOVE P3,T1 ;SAVE RET PAIR
MOVN T3,T1 ;GET -VE SIZE IN THIS GROUP
ADDM T3,LERBLK+.RBALC ;ADJUST COUNT FOR NEXT TIME
MOVE T1,T2 ;GET BASE LBN
PUSHJ P,SUSET ;POSITION DISK
POP P,T1 ;GET BACK THE OLD P3
JUMPL T1,[POP P,T3
POP P,T2
POP P,T1
POPJ P,]
POP P,T3
POP P,T2
POP P,T1
JRST OUT20F ;TRY AGAIN
OUT22F: TYPE <% Output error >
GETSTS VIO,T1
PUSHJ P,OCTOUT
OUT23F: TYPE < for >
PUSHJ P,PUTER0
TYPE <, block >
MOVE T1,BLKCNT
PUSHJ P,DECOUT
PUSHJ P,CRLF
JRST .ERR
; ROUTINE TO CLEAR OUT THE I/O BUFFER
ZAPBFR: PUSHJ P,SAVE2
HRRZI P1,1(T1)
SETZM (P1)
MOVEI P2,177(P1)
HRLI P1,(P1)
ADDI P1,1
BLT P1,(P2)
POPJ P,
;HERE TO XFER AN ASCII MODE FILE
C$PUTC: SETOM RSXCTR ;START OFF BUFFERED POINTER
SETZM BLKCNT ;# BLOCKS IN FILE
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
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?
JRST C$PUTE ;COPY A SEQ'ED 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 PUTEOF ;ODD, NULL FILE
;HERE TO XFER A NORMAL ASCII MODE FILE
C$PUTF: MOVSI T1,-<1000*5-1> ;COUNT OF MAX CHARACTERS PER LINE
MOVE T2,[POINT 7,LINBUF] ;POINT AT LINE BUFFER
$PUTF1: PUSHJ P,GETC ;GET A BYTE
JRST [TDO F,[X%EOF] ;REMEMBER EOF
JRST $PUTF2] ;SKIP AHEAD
JUMPE T3,$PUTF1 ;IGNORE NULLS
CAIN T3,15 ;IGNORE CR'S
JRST $PUTF1 ;...
PUSHJ P,TRMSK0 ;SKIP IF A TERMINATOR CHARACTER
AOBJN T1,[IDPB T3,T2 ;LOOP IF STILL ROOM, INSERT CHAR
JRST $PUTF1] ;...
HRRZS T1 ;ISOLATE CHARACTER COUNT
;HERE IF WE FIND END OF LINE
$PUTF2: PUSH P,T1 ;SAVE BYTE COUNT
MOVE T3,(P) ;GET LOW BYTE
PUSHJ P,PUT20F ;SAVE LOW BYTE OF COUNT IN 20F FILE
LDB T3,[POINT 8,T1,27] ;GET HIGH BYTE OF COUNT
PUSHJ P,PUT20F ;SAVE HIGH BYTE TOO
MOVE T2,[POINT 7,LINBUF] ;GET POINTER
HRRZ T1,(P) ;RESTORE T1
JUMPE T1,$PUTF4 ;SKIP XFER OF BYTES IF NONE THERE
$PUTF3: ILDB T3,T2 ;GET A BYTE
PUSHJ P,PUT20F ;PUT BYTE IN 20F FILE
SOJG T1,$PUTF3 ;LOOP TILL LINE XFERRED
$PUTF4: POP P,T1 ;RESTORE BYTE COUNT
MOVEI T3,0
TRNE T1,1
PUSHJ P,PUT20F ;INSERT DUMMY IF ODD BYTE COUNT
TDZN F,[X%EOF] ;SKIP IF END OF FILE
JRST C$PUTF ;GO GET ANOTHER LINE
JRST PTAEOF ;JOIN COMMON CLOSE FILE CODE
;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: PUSHJ P,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
PUSHJ P,PUT20F ;SAVE LOW BYTE OF COUNT IN 20F FILE
LDB T3,[POINT 8,(P),27] ;GET HIGH BYTE OF COUNT
PUSHJ P,PUT20F ;SAVE HIGH BYTE TOO
MOVE T3,LINNUM ;GET LOW BYTE OF SEQ#
PUSHJ P,PUT20F ;PUT HIGH BYTE OF COUNT IN FILE
LDB T3,[POINT 8,LINNUM,27] ;GET HIGH BYTE OF SEQ#
PUSHJ P,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
PUSHJ P,PUT20F ;PUT BYTE IN 20F FILE
SOJG T1,$PUTE3 ;LOOP TILL LINE XFERRED
POP P,T1 ;RESTORE BYTE COUNT
TRNE T1,1
PUSHJ P,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)
PUSHJ P,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: MOVEI T1,BLKBFR
PUSHJ P,OUT20F ;PUT OUT LAST PARTIAL BUFFER
PTIEOF: 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 #
;FALL INTO PUTEOF
;HERE WHEN WE ARE FINISHED XFER'ING TO A 20F OUTPUT FILE
PUTEOF: SUB P3,P1 ;COMPUTE P3=# BLOCKS THIS GROUP USED
DMOVE T1,P3 ;GET RET PAIR FOR THIS GROUP
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
TDZN 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
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
PUSH P,T1 ;USE NO ACS
MOVS T1,RSXPTR ;GET PDP11 BYTE POINTER INTO BUFFER
PUSHJ P,PUTBYT ;INSERT BYTE
AOS RSXPTR ;INCREMENT BYTE POINTER
POP P,T1 ;RESTORE T1
POPJ P, ;RETURN
PUT21F: PUSH P,T1 ;USE NO ACS
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
POP P,T1
JRST PUT20F ;TRY AGAIN
;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 CPOPJ1 ;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>
POPJ P, ;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
PUSHJ P,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
TYPE <% INPUT ERROR READING FILE FROM FE DISK>
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,^D8
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?
MOVE T2,[777400,,777400] ;MUST BE NICE AND SMALL UIC
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,.FXDIM(FP) ;NO WILD CARDS IN PPN
SKIPE .FXDIR+2(FP) ;NO SFDS PLEASE
PUSHJ P,ILLCMD
TDNE T2,.FXDIR(FP) ;UIC MUST BE IN RANGE
PUSHJ P,ILLCMD
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
HLRZ T1,.FXDIR(FP) ;GET PROJECT #
IDIVI T1,100 ;MAKE T1=1ST DIGIT, T2=2ND*10+3RD
IDIVI T2,10 ;MAKE T2=2ND, T3=3RD
LSH T1,^D12 ;MAKE T1=1ST DIGIT IN SIXBIT POSITION
LSH T2,^D6 ;MAKE T2=2ND DIGIT IN SIXBIT POSITION
IORI T1,'000'(T2) ;MAKE T1=1ST DIGIT+2ND DIGIT, SIXBIT FMT
IORI T1,(T3) ;MAKE T1=OLD + 3RD DIGIT
HRLZM T1,UFDFDB+.FXNAM ;SPECIFY NAME OF FILE
HRRZ T1,.FXDIR(FP) ;GET PROGRAMMER NUMBER
IDIVI T1,100 ;MAKE T1=1ST DIGIT, T2=2ND*10+3RD
IDIVI T2,10 ;MAKE T2=2ND, T3=3RD
LSH T1,^D12 ;MAKE T1=1ST DIGIT IN SIXBIT POSITION
LSH T2,^D6 ;MAKE T2=2ND DIGIT IN SIXBIT POSITION
IORI T1,'000'(T2) ;MAKE T1=1ST DIGIT + 2ND DIGIT IN SIXBIT
IORI T1,(T3) ;MAKE T1=OLD + 3RD DIGIT TOO
HRRM T1,UFDFDB+.FXNAM ;SPECIFY NAME OF FILE
SETOM UFDFDB+.FXNMM ;MAKE NAME NOT APPEAR WILD
SETZM UFDFDB+.F2NAM ;MAKE SURE NAME IS "SHORT" 6 LETTER FORM
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!
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
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
MOV. [.RAD50 <DIR>],FTYP,P2 ;STORE FILE TYPE INTO OUR FHB
MOV. [.RAD50 <DIR>],UFTY,P3 ;STORE FILE TYPE IN DIRECTORY TOO
STOR. [1],UFSQ,P3 ;STORE SEQ# IN DIRECTORY
STOR. [1],FSEQ,P2 ;STORE SEQ# IN FHB
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,^D32
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 8,T1,27] ;GET HI BYTE
STOR. T2,HIBH,P2 ;REMEMBER IT
; STOR. [0],HIBH,P2 ;...
STOR. T1,HIBL,P2 ;HIGH BLOCK IN USE IS 1
AOS T1 ;UP BY ONE TO GET EOF BLOK#
LDB T2,[POINT 8,T1,27] ;GET HI BYTE
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],UFX0,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
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
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
SKIPN DSKBLK+.DCSNM ;MUST BE MOUNTED VOLUME
ERROR <Cannot ZERO an offline volume>
PUSHJ P,MKFESY ;MAKE THE FE.SYS FILE
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,STORET ;...STORE RETRIEVAL POINTERS
; WRITE THE FHB
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],HIBK ;HIGHEST BLOCK IN USE=1
STOR. [0],HIBH
STOR. [1],HIBL
; STOR. [2],EFBK ;SO EOF BLOCK = 2
STOR. [0],EFBH ;
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
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
MOVE P3,FSTLBN ;GET END OF REGION (IE: BLK CNT)
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 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
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,
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>]
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
MOVE P1,T1 ;COPY P1=FHB BUFFER ADDRESS
SUBI P1,FHBBUF ;COMPUTE PDP10 OFFSET
IMULI P1,4 ;AND THEN COMPUTE PDP11 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
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
POPJ P,
; ROUTINE TO INITIALIZE THE FILE HEADER BUFFER
INIFHB: PUSHJ P,SAVE2 ;SAVE SOME ACS
DMOVE P1,T1 ;P1=FILE #, P2=FHB BUFFER
SETZM (T2) ;START TO ZERO IT OUT
HRLI T2,(T2) ;COPY ADDRESS
ADDI T2,1 ;TURN INTO BLT POINTER
BLT T2,177(P2) ;ZERO THE INITIAL FHB
SUBI P2,FHBBUF ;CREATE PDP10 OFFSET
IMULI P2,4 ;...AND THEN PDP11-IZE THAT
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
;
;ENTER:
; T1/ FILE # OF FILES-11 FHB
; 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
ERROR <SCNRET failed to find INDEXF block>
REDFH1: PUSHJ P,SUSET ;POSITION DISK
POP P,T1 ;RESTORE 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
POPJ P, ;RETURN IF I/O WAS GOOD
ERROR <I/O error reading FHB>
; ROUTINE TO WRITE A "USER" FILE-HEADER-BLOCK
;
; T1/ POINTER TO BUFFER TO WRITE
WRUFHB: PUSHJ P,SAVE4 ;SAVE SOME ACS
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
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
POPJ P, ;DONE
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,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
; ROUTINE TO WRITE THE FILE-HEADER-BLOCK BUFFER ONTO CORRECT DISK BLOCK
WRTFHB: LOAD. T1,FNUM ;LOAD T1=FILE# FROM FHB BUFFER
SUBI T1,1 ;CONVERT FILE# TO ABSOLUTE FILE INDEX#
JUMPL T1,[ERROR <Illegal file number 0>]
IDIVI T1,^D32 ;LOAD T1=WORD# IN IBM, T2=RELATIVE BIT#
ADD T1,IBMINC ;CONVERT T1=ADDRESS OF CORRECT IBM WORD
MOVE T2,B32TBL(T2) ;CONVERT T2=CORRECT BIT MASK WITHIN WORD
ORM T2,@T1 ;TURN ON BIT FOR THIS FHB IN THE IBM
MOVEI T1,FHBBUF ;LOAD T1=POINTER TO THE CURRENT FHB
MOVEI T2,O.CKSM/2 ;LOAd T2=#WORDS TO CHECKSUM
PUSHJ P,CHKSUM ;LOAD T1=CHECKSUM OF (T1/T2) BLOCK
STOR. T1,CKSM ;INSERT THE CHECKSUM INTO FHB BUFFER
LOAD. T1,FNUM ;LOAD T1=FILE NUMBER OF FHB BUFFER
ADD T1,FHBLBN ;COMPUTE T1=BLOCK# WITHIN INDEX LIST
SUBI T1,1 ;ACCOUNT FOR THE FACT FILE#S START AT 1
PUSHJ P,SUSET ;POSITION DISK
OUT VIO,[IOWD 200,FHBBUF ;WRITE THE FHB BUFFER ONTO DISK
0] ;
SKIPA
ERROR <OUT failed at WRTFHB>
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
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
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:
>
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 <:[>
HLRZ