TITLE RIPOFF V.5 CUSP level disk management program SUBTTL Assembly and loading instructions ; Created at Southern Methodist University ; Supported by Alpha Systems Inc, Dallas Texas ; by Steve Bush begun 13-Jul-71 ; ; Highly modified at the University of Arizona, ; Tucson, Arizona 1-Nov-77 LOGIC==0 ; For REPEAT LOGIC, REPEAT LOGIC,< For loading , without DDT do: .LOAD RIPOFF .[N]SSAVE For loading with DDT, gets a little more difficult. The last location in RIPOFF's low seg (whether pure or not) is called LOWSIZ:. Only reference to this symbol is at RIPSIZ:, which is on the first page of code in this listing, and reads approximately RIPSIZ: MOVEI T,LOWSIZ MOVEM T,.JBFF CORE T, This fixes core, which RIPOFF dynamically allocates for tables after LOWSIZ. To keep DDT and symbols from getting wiped out in the process, simply enter DDT after loading and examine .JBFF to determine full size of low segment and patch RIPSIZ: to correspond. That is, .R LINK *RIPOFF/LOCALS,SYS:DDT.REL/GO ; DDT must load after RIPOFF. .DDT RIPOFF$: .JBFF/ 14206 RIPSIZ/ MOVEI T,LOWSIZ MOVEI T,14206 ^C .[N]SSAVE RIPDDT To make patches at any time, simply make them starting at 14206 (which you may define symbolically to DDT as PATCH:) and retype instruction at RIPSIZ to refer to the location just beyond your patch. Note that I use 14206 only as an example. The actual number you find there will change. > SUBTTL Revision history COMMENT ` Revision history since version 4 1-Jan-74 [1] 15-Apr-74 Fixed SYSINI and %RP10 to know about RP03's [2] 10-Jun-74 Added KISW and fixed PNTCOR to print pages on KI-10. Also changed LOCK to %LOCK so no confusion with UUO. [3] 02-Jul-74 Fixed /P bug wasnt zeroing WASTEB and TFILCT. Added 'Error summary for DSKx' message in /PE code. [4] 25-Jul-74 Corrected table %RP10 - had 400 blocks/cylinder for RP03's. They are 200 blocks/cylinder. [5] 01-Jan-75 Corrected access date byte pointer (DATE75) [6] 15-Sep-75 Added /DT function to delete files meeting access and creation data criteria. [7] 16-Sep-75 Redid logic at SYSIN2 (which determined type of disk pack) to be more general. Also added RP04's to tables. [10] Redid patching logic. Added LOWSIZ: and took out use of external symbol PAT. See assembly instructions at the beginning of this listing. [11] Fix DSKLST code. Remove tape label and version. Add number of RIB ptrs and extended RIB flag. Histogram number of RIB ptrs. Remove logic to provide different format for TTY than for hard copy. One format only. [12] Changed a bunch of OCTPRT's to DECPRT's. All block numbers, cluster addresses, etc in decimal now. No more dot to indicate decimal numbers. Context should be clear. [13] Added SUSET. UUO's under assembly switch SUPSW, normally on. [14] 14-Jun-76 Preparing to submit to DECUS. Removed all assembly switches except PURESW. Have RIPOFF determine KA/KI/KL rather than assembly switch. Have it determine if SUSET. UUO exists instead of assembly option. Clean up disk code and fix RP04 in tables. Revision history continued [15] 15-Jul-76 Incorporate edits from suggestions from LUG users. Treat *.*[*,*]/D as a special case, issue warning. Add [10,1] to VIPS. Round KA core size to K not pages. Fix incorrect block number printout in SAT listing. Change default output to TTY: Make = work like left arrow, replace = as used in /EC with == double equal. Make "K for swapping" print right. [16] 27-Oct-76 Add RP06 table. University of Arizona local modifications Start version 5 here [17] 14-Mar-77 Add SFD support [20] Clean up the convoluted and poor code. [21] Get standard symbols from JOBDAT, UUOSYM, and MACTEN. [22] Add support for DPC. [23] Change block numbers back to octal, thus removing part of edit 12. [24] Add the /ETS, /ETL, and /ETN switch options. [25] Add the /F switch [26] Make the /V code a little more careful about writing the listing to the same structure being DSKRATed. [27] Add new words to RIB for 603 [30] Print the checksum from the pointer in the /PR code [31] Allow a range and increment [m= relsiz instead of PPNs with more than relsiz blocks. This was more useful to us. [73] 08-Mar-78 Add the /DM option to force the delete routines to use the monitor RENAME only. [74] 08-Mar-78 Don't let the /AM switch be used on a mounted STR. [75] 26-Apr-78 Prevent /IR from messing up creation date on restored files. (U. of Texas) [75] 11-May-78 RIPOFF loops if the user types a ^Z at command level. Make ^Z look like ^C. Also ignore spaces and tabs correctly. [76] 19-May-78 RIPOFF doesn't know about RS04's. Add support for them [77] 8-Aug-78 Report of files found is garbage when wildcard is used with /FD switch [TCSAPA]3-21-80 Mark in SAT the blocks pointed to by BAT. /SMW [TCSAPC]3-25-80 Make RIPOFF know about RPD's, per request of DEC Phoenix /SMW ` SUBTTL Bits and pieces SEARCH JOBDAT,MACTEN,UUOSYM ; Get standard symbols SALL ; Clean up the listing RIPVER==5 ; Major edit number RIPMIN==0 ; Minor edit number RIPEDT==77 ; Last edit number RIPWHO==4 ; Programmer - SRB/GMU LOC <.JBVER> VRSN. (RIP) ;; Plug version number RELOC PURGE RIPVER,RIPMIN,RIPEDT,RIPWHO ; Conditional assembly switches IFNDEF PURESW, ; Two segment shareable program ; Set up relocation IFN PURESW, < TWOSEG RELOC 400000 .ZZ==.JBDA ; First low segment location > IFE PURESW, SUBTTL Accumulator and I/O channel definitions F=0 ; Flags and switches T=1 ; First of 5 temp AC's T1=2 ; T2=3 ; T3=4 ; T4=5 ; N=6 ; Numbers across I/O subroutines N1=7 ; N+1 for remainders CH=10 ; Characters M=11 ; Message pointer and temp AC U=12 ; Unit P1=13 ; First of 4 temp pointers P2=14 ; P3=15 ; P4=16 ; SW=P3 ; Switch bits live here P=17 ; Pushdown pointer ; Monitor I/O channels CMD==0 ; TTY cmd channel LST==1 ; The list device STR==2 ; Disk channel used for all temporary disk I/O AUX==3 ; Auxillirary channel for scratch output device FFCHAN==4 ; First free channel SUBTTL Flag bits ; Bits in LH of F .DEV==1B17 ; Seen a device .DOT==1B16 ; Seen a dot .EXT==1B15 ; File extension has been typed .LBRKT==1B14 ; Left bracket seen .COLON==1B13 ; Seen a colon .BCHR==1B12 ; AC 'CH' contains break char already. .LBS==1B11 ; Pound sign (#) seen. F.MFD==1B17 ; MFD has been 'LOOKED UP' on str F.RALL==1B16 ; Read all blocks in BLDSAT F.TMP==1B15 ; Tempory flag for any use F.SCAN==1B14 ; Force NXTFIL to treat SFDs as directories F.OURS==1B13 ; Mark bits in our SAT F.TRB==1B12 ; Be on lookout for differences in above two SATS F.MDEL==1B11 ; Use the monitor RENAME only in DELFIL/DELUFD F.RIB==1B9 ; Used by RIBCHK F.MULT==1B8 ; Multiply used clusters found F.CRLF==1B7 ; No carriage returns between blocks in ASCOUT F.1UNI==1B6 ; INIT'ed STR points to only one unit S.SFD==1B4 ; All SFD levels are * in command string S.NAM==1B3 ; Ditto for filename S.EXT==1B2 ; Ditto for extension S.PROG==1B1 ; Ditto for programmer number S.PROJ==1B0 ; Ditto for project number STNDRD==S.PROJ!S.PROG!S.NAM!S.EXT!S.SFD ; Default command string is ALL:*.*[*,*,*,*,*,*,*] ; Flags (In RH of F) F.TTY==1B35 ; TTY output F.TTY2==1B34 ; Force TTY output for all output (user assigned TTY LPT) F.FAIL==1B33 ; Something failed F.INI==1B32 ; DSK channell is INIT'ed. F.IO==1B31 ; 1 if writing, 0 if reading F.NULL==1B30 ; Null UFD F.TRY==1B29 ; Try count for BLKRED,BLKWRT F.CSUM==1B28 ; Tell BLKRED to checksum block F.ERRM==1B27 ; About to print an error msg. No tab on output F.TYPE==1B26 ; 1=DP,0=FH, Used by DEVERR F.DBAD==1B25 ; Delete only if file is bad (/DB) F.RIP==1B24 ; Restore in progress (/I code) F.QUICK==1B23 ; Quick option in BLDSAT (/VQ) F.NEWR==1B22 ; New RIB just read by GETPTR (Extended RIB) ; (Flag zeroed every call otherwize) F.DERR==1B21 ; For SYSINI to tell BLKRED data error expected. ; BLKRED supresses printing of error message. F.NOTB==1B20 ; Force NAMPNT to use dot instead of tab ; between filename and ext F.NPP==1B19 ; NXTPPN called instead of NXTDIR F.LEN==1B18 ; Force DMPIN to ignore length of the file contained ; in the RIB and give EOF return only when the ; RIB pointers are exhausted SUBTTL Switch bit definitions REPEAT LOGIC,< Switches are typed to RIPOFF in the form of /AXYZ/BQRST Where A and B are the actual switches and XYZ are the A options and QRST are B options. E.g., to use /P (print disk listing) and print SATS and BATS only (S and B options), one would type STR:/PSB The first switch character after the / is read and saved, and all following chars up to the next / or line delimiter are taken as the options which apply to that switch. The options live in AC 'SW' as follows: A-Z Set bits 35-10 respectively in SW 0-9 Sets bits 9-0 respectively. The following macros define these bits. Switches may be tested by TXN{E,N} SW,CH.X where 'X' is the switch to be tested. > SALL DEFINE SWMAC (X) < IRPC X,>>> SWMAC (ABCDEFGHIJKLMNOPQRSTUVWXYZ) DEFINE SWMAC(X) < IRPC X,< CH.'X==1B<^D9-X>>> SWMAC (0123456789) SUBTTL COMMOD parameter definitions ; ; The following three pages contain BAT block, HOME block, ; and RIB definitions from COMMOD. BE SURE that the following ; definitions agree with those in your version of COMMOD. ; ; ; BAT block definitions BAFNAM==0 ; SIXBIT /BAT/ BAFFIR==1 ; -Cnt free wrds,,Rel. adr. of 1st bad region BAFNBS==2 ; Contains BAYNBS,BAYNBR,BAYKND pointers BAYNBS: POINT 9,BUF+BAFNBS,8 ; # Bad sectors found by map BAYNBR: POINT 9,BUF+BAFNBS,17 ; # Bad regions found by map BAYKDC: POINT 7,BUF+BAFNBS,24 ; Kontroler device code BAFCNT==3 ; # Pairs added by MONITOR BAFREG==4 ; First bad region pair goes here BAPOTH==400,,0 ; Non-zero if blocks found by other Kontroler also BAPNTP==40000 ; Non-zero if new-type entry BAYNBB: POINT 9,-1(P2),8 ; Number of bad blocks in this region BAYPUB: POINT 8,-1(P2),17 ; Physial unit within Kontroller BAYKNM: POINT 3,-1(P2),20 ; Logical Kontroller number BAYAPN: POINT 14,-1(P2),35 ; Processor number BAYERR: POINT 6,(P2),8 ; Error bits on new entry BAYELB: POINT 27,(P2),35 ; Block adr of bad region in new entry BAFCOD==176 ; Contains unlikely code (606060) CODBAT==606060 ; The code itself BAFSLF==177 ; This block in unit ; HOME block definitions HOMNAM==0 ; "HOM" in SIXBIT HOMHID==1 ; SIXBIT unit id HOMPHY==2 ; Physical address of this block,,other home block HOMSRC==3 ; Position of this STR in SYS search list HOMSNM==4 ; SIXBIT structure name HOMNXT==5 ; ID of next unit in file structure HOMPRV==6 ; ID of previous unit in file structure HOMLOG==7 ; SIXBIT logical unit # within file structure HOMLUN==10 ; Logical unit in STR HOMPPN==11 ; Proj-prog # which refreshed STR HOMHOM==12 ; LH==Logical block # within unit of Home block ; RH==Log. block # within unit for extra Home block HOMGRP==13 ; # of blocks per group to try for HOMBSC==14 ; # blocks per supercluster on this unit HOMSCU==15 ; # of superclusters per unit HOMCNP==16 ; Byte ptr for cluster count in RIBS HOMCKP==17 ; Byte ptr for checksum in RIB HOMCLP==20 ; Byte ptr for cluster address in RIB HOMBPC==21 ; # blocks per cluster for this STR HOMK4S==22 ; # K words for swapping on this unit HOMREF==23 ; Non-zero if file must be refreshed HOMSIC==24 ; # SAT blocks in core HOMSID==25 ; Unit ID of next unit in active swapping list HOMSUN==26 ; Logical unit # in active swapping list HOMSLB==27 ; First log. block # for swapping on this unit HOMCFS==30 ; Swapping class HOMSPU==31 ; # SAT blocks per unit HOMOVR==32 ; Overdrawn limit per user on this STR HOMGAR==33 ; Upper bound on total reserved blocks HOMSAT==34 ; SAT.SYS (Log. block within STR of first RIB) HOMHMS==35 ; HOME.SYS HOMSWP==36 ; SWAP.SYS HOMMNT==37 ; MAINT.SYS HOMBAD==40 ; BADBLK.SYS HOMCRS==41 ; CRASH.SAV HOMSNP==42 ; SNAP.SAV HOMRCV==43 ; RECOV.SYS HOMSUF==44 ; SYS UFD [1,4] UFD HOMPUF==45 ; Printer UFD [3,3] HOMMFD==46 ; MFD [1,1] HOMPT1==47 ; First retrieval ptr for MFD HOMUN1==50 ; Logical unit # where MFD starts HOMLEN==51 ; Table of lengths of files created by refresh - 6 words HOMEND==56 ; Last word kept in UDB copy of Home block HOMUTP==57 ; Unit type on which HOM block was written HOMRIP==60 ; Used by RIPOFF (That's not us) HOMKLB==61 ; First of 20 words used by PDP-11 in KL10 systems HOMKLE==104 ; Last of the 20 words HOMK4C==105 ; K for CRASH.EXE file HOMBTS==106 ; Bits in the HOM block HOMPVS==1B35 ; Unit contained in a private STR HOMVID==165 ; Volume ID (3 words, 12 PDP-11 bytes) HOMOWN==170 ; Owner name (3 words, 12 PDP-11 bytes) HOMVSY==173 ; System type (3 words, 12 PDP-11 bytes) HOMCOD==176 ; Contains XWD 0 ,, 707070 (unlikely code) CODHOM==707070 ; Unlikely code for HOMCOD HOMSLF==177 ; This block # within unit ; RIB definitions RIBFIR==0 ; XWD -Nr. of retrieval ptrs ,, First pointer adress RIBPPN==1 ; XWD Project ,, Programmer number RIBNAM==2 ; SIXBIT file name RIBEXT==3 ; SIXBIT file extension ,, Access date EXLHCD: POINT 3,BUF+RIBEXT,20 ; 3 high order bits of creation date EXLACD: POINT 15,BUF+RIBEXT,35 ; Access date RIBPRV==4 ; Priv. bits ,, mode ,, creation time ,, creation date EXLPRV: POINT 9,BUF+RIBPRV,8 ; Protection code EXLMOD: POINT 4,BUF+RIBPRV,12 ; Creation mode EXLCRT: POINT 11,BUF+RIBPRV,23 ; Creation time EXLLCD: POINT 12,BUF+RIBPRV,35 ; 12 low order bits or creation date RIBSIZ==5 ; File length in words RIBVER==6 ; Prog # making last change ,, octal version # RIBSPL==7 ; Spooled device RIBEST==10 ; Estimated length of file in blocks RIBALC==11 ; # of blocks allocated for file RIBPOS==12 ; Log block # in STR of last group RIBFT1==13 ; Reserved for future use by DEC RIBNCA==14 ; Word for customer to define RIBMTA==15 ; Tape label if file on magtape RIBDEV==16 ; Name of STR containing file RIBSTS==17 ; Status bits RIPLOG==1B0 ; User logged in RIPDIR==1B18 ; This is a directory RIPNDL==1B19 ; No deletion of this file by any user! RIPNCN==1B20 ; No name change permitted RIPNFS==1B21 ; Not to be dumped by BACKUP RIPABC==1B22 ; Always bad checksum (SWAP.SYS, SAT.SYS) RIPABU==1B24 ; Always backup this file RIPPAL==1B25 ; Pre-allocated file RIPSCE==1B27 ; File has checksum error RIPHWE==1B28 ; File has had hard write error RIPHRE==1B29 ; File has had hard read error RIPBFA==1B32 ; File found bad by BACKUP during restore RIPCRH==1B33 ; File closed after crash RIPBDA==1B35 ; File found bad by damage assesment program RIBELB==20 ; Log block # where bad region begins RIBEUN==21 ; Err unit # in STR ,, Nr bad blocks in region RIBQTF==22 ; FCFS quota for this PPN in this STR (UFD only) RIBQTO==23 ; Logged out quota (UFD only) RIBQTR==24 ; Reserved quota (UFD only) RIBUSD==25 ; Nr blocks used when job was last logged out (UFD only) RIBAUT==26 ; Author - PPN writing the file RIBNXT==27 ; Next STR for this file (unused level D) RIBPRD==30 ; Previous STR for file (unused level D) RIBPCA==31 ; Privileged arg for customer definition RIBUFD==32 ; Block # in STR of UFD data block with ptr to this RIB RIBFLR==33 ; First logical block in file pointed to by this RIB ; (zero if first RIB) RIBXRA==34 ; Extended rib address DEYRBU: POINT 4,SAVXRA(P4),12 ; Unit DEYRBA: POINT 23,SAVXRA(P4),35 ; Cluster address DEYRBC: POINT 8,SAVXRA(P4),8 ; Count RIBTIM==35 ; Time,,Date word in universal standard RIBLAD==36 ; Last accounting date (UFD) RIBDED==37 ; Directory expiration date (UFD) RIBACT==40 ; AOBJN pointer to account string RIBENT==RIBACT ; Last arg or value on extended lookup/enter/rename RIPNUB==400000 ; Bit in retrieval ptr says new unit RIBCOD==176 ; Contains 777777 (unlikely code) CODRIB==777777 ; Unlikely code for RIBCOD RIBSLF==177 ; This logical block number in STR SUBTTL Internal device table definitions REPEAT LOGIC,< The unit data blocks (UDB's) are created as RIPOFF begins execution, one for each unit in the system. These UDB's contain all information about the units pertinent to RIPOFF, as defined below. They are connected by a linked list starting in UNIDDB (RH), linking through the right half of the first word in each UDB. AC U is reserved for the current UNIDDB address. To 'INIT' a structure, a call is made to NXTSTR (PUSHJ). Here, the next (or first) structure or device is set up, in accordance with the command string. Within NXTSTR, all physical units involved in the current str or device are linked through the left half, begining at UNIDDB (LH). Thus to find all units pertinint to the current structure, transverse the LH. Transversing the right branches finds all units in the system. In addition to the UDB's, the following two tables are also of interest. STRTAB - Contains the SIXBIT name of each structure in the system, followed by the address of the UDB's for each unit in the STR. Set up at system initialization (SYSINI). Note that this is a compressed table, i.e., the number of entries following each SIXBIT structure name is precisely the number of units in that structure. STRUNI - Block of 8 words which are the addresses (in order) of all UDB's in the present structure. Set by each 'INIT' (NXTSTR). > ; Each UDB setup at system initialization contains the first ; 57 words of the HOM block (HOMNAM through HOMEND) as the first ; 57 words of the UDB. In addition, each UDB contains the ; following words: ; DEFINE UUU(X,Y) < UNIDDL=UNIDDL+Y X=UNIDDL > UNIDDL=HOMEND ; The first 57 words of the Home block are ; always in the UDB. ;***** Note: Do not change order here without changing order ; in UNITAB ******* UUU(UNIWPS,1) ; Words/SAT for this unit UUU(UNICPS,1) ; Clusters/SAT for this unit UUU(DRIVE,1) ; Physical device name pack is on (DPA3,FHA0) UUU(DEVKON,1) ; XWD unit within controler ,, Contr. type ; (See TYPMAX) UUU(BLKCYL,1) ; Blocks/cylinder on unit UUU(BLKTRC,1) ; Blocks/track on unit UUU(BLKUNI,1) ; Blocks on this unit ;**** End of dont change order (This is all the info printed...) UUU(UNISTS,1) ; CONI word after last interrupt from unit UUU(XCHAN,1) ; Z chan,T (Inited channel in AC field, T in adr.) UUU(CURPOS,1) ; Last block this unit positioned to. UUU(DSKSAT,1) ; Initial pointer to core copy of disk SATs UUU(OURSAT,1) ; Initial ptr to our version of SATs UUU(TRBSAT,1) ; Log of difference between above two SATs UUU(UNIDES,1) ; DSKCHR bits for unit UUU(PATDDB,3) ; Patching space for debugging ;**** Add new words above this line UNIDDL==UNIDDL ; So we can see it in CREF listing SUBTTL Miscellaneous parameters ; ; General disk parameters BLKSIZ==200 ; Length of disk blocks HEDNUM==3 ; Number of words in I/O header block LHOM1==1 ; Logical address of first Home block LHOM2==12 ; Logical address of second Home block MAXSTR==^D13 ; Maximum number of file structure on this system ; (Used only to limit table sizes) MAXUNI==7 ; Number of highest unit on a controller DUFD==700000 ; Standard UFD protection DPRT==155000 ; Standard file protection STRQUE==SIXBIT/DSKB/ ; Structure to be assumed for queue ; if GETTAB fails SFDLVL==5 ; Max level for SFD nesting PDLSIZ==50 ; Size of the PDL ; ; File status bits ; RH bits in IOSTS(P4) are taken from the RIB ; LH bits in IOSTS(P4) are internally used bits IO.FAC==1B0 ; File is active (LOOK'ed UP and not hit EOF) IO.CKS==1B1 ; Checksum error IO.WRT==1B2 ; 1=File being written, 0=Reading ; ; Extended LOOKUP/ENTER parameters EXLLEN==32 ; Number of extended lookup args EXLERC==3 ; Error code found in this word of LOOKUP/ENTER block EXLERB: POINT 10,BUF+RIBSTS,35 ; Error bits ; ; Parameters for EOF block (on AUX device) EOFNAM==0 ; SIXBIT /EOF/ EOFCOD==176 ; Contains unlikely code CODEOF==506070 ; The code EOFSLF==177 ; This word within file (not implemented yet!) ; ; Some useful opdefs OPDEF TTYON [TRO F,F.TTY] ; Enable TTY output OPDEF TTYOFF [TRZ F,F.TTY] ; Disable TTY output ; ; and general bits of crud TOPHIS==^D50 ; Highest file size to look for in histogram MAXCMD==^D60 ; Max number of ASCII command string characters PAGSIZ==^D58 ; Number of lines per printer page BUFNUM==0 ; Number of buffers for LPT and TTY (use monitor default) DLPT=='LPT' ; These are the default device names DLST=='LST' ; and also help DDT printout DDSK=='DSK' ; More meaningful codes DSYS=='SYS' DTTY=='TTY' DCTY=='CTY' UFD6=='UFD' SUBTTL Storage macro definitions IFE PURESW,< DEFINE UU(A,B) > IFN PURESW,< DEFINE UU(A,B) < A=.ZZ .ZZ=.ZZ+B >> DEFINE U(A) < UU(A,1) > ; Macro for generating error tables DEFINE ERRMAC(X,Y) < XWD [ASCIZ/X/] , [ASCIZ/Y/] > ; Some useful macro op-code definitions DEFINE MOV (X,Y) ;; Move from memory to memory (uses T) < MOVE T,X XLIST MOVEM T,Y LIST > DEFINE MOVI (X,Y) ;; Move immediate to memory (Uses T) < MOVEI T,X XLIST MOVEM T,Y LIST > DEFINE MOVPTH (X,Y) ;; Move PATH. block in memory (Uses T) < IFG SFDLVL, < MOVE T,[X,,Y] XLIST BLT T,Y+.PTPPN+1+SFDLVL+1-1 LIST > > SUBTTL RIPOFF main routines RIPOFF: JFCL ; No CCL entry RESET ; Reset everthing MOVI SWT.X,.JBREN ; Setup reentry address MOV <[4,,CCEXIT]>,INTBLK+.ERNPC ; Setup ^C intercept block MOVI ER.ICC,INTBLK+.ERCLS ; contents SETZM INTBLK+.EROPC ; and clear rest of block SETZM INTBLK+.ERCCL MOVI INTBLK,.JBINT ; and setup for intercept MOVE P,PDP ; Setup pushdown list GETPPN T, ; Get our PPN JFCL ; Avoid stupid skip MOVEM T,OURPPN ; and save for later MOVX T,%LDFFA ; GETTAB for GOD PPN GETTAB T, ; Get it MOVE T,[1,,2] ; Assume the obvious CAMN T,OURPPN ; Same as ours? JRST RIP1 ; Yes, good enough PJOB T, ; Get our job number MOVNS T ; Negate it JOBSTS T, ; Get our job's status SKIPA ; Too bad TXNN T,JB.UJC ; Job running with JACCT? JRST BADBOY ; No, not privledged enough RIP1: SETZB F,%SUSET ; Clear flags and assume no SUSET. UUO MOVEI T,.IODMP ; Open dump mode channel SETZB T1,T2 ; No buffers + setup for SYSSTR SYSSTR T1, ; Get structure name to use JRST RIP2 ; Can only hope the rest will work OPEN STR,T ; Open the channel JRST RIP2 ; What can we do? MOVE T,[Z STR,1] ; Set to read block 1 SUSET. T, ; Try it JRST RIP2 ; Didn't work, use USETO/I STATO STR,IO.IMP!IO.BKT ; Any errors? SETOM %SUSET ; Flag SUSET. as OK RIP2: RESET ; Reset the world again RIPSIZ: MOVEI T,LOWSIZ ; Build free core after LOWEND ; This location must be altered ; whenever patches are made MOVEM T,.JBFF ; Tell monitor our correct field length CORE T, ; Adjust core to this value JFCL ; Oh well IMULI T,^D1024 ; Compute CORMAX from 1K blocks returned IFN PURESW, < SUBI T,400000 ; Can't core up into high seg > MOVEM T,.JBMAX ; Highest loc available to low segment SETZ T, MOVSI T1,DTTY ; First get us a TTY MOVE T2,[XWD WH.CMD,RH.CMD] OPEN CMD,T JRST NOTTY SETZ T, MOVSI T2,WH.LST MOVSI P1,DLST DEVCHR P1, ; Look for a listing device JUMPE P1,HAVETT ; No .ASS DEV LST..Use TTY TXNE P1,DV.TTY ; .ASS TTY LST? JRST HAVETT ; Yes. Use it. MOVSI T1,DLST ; No. Use device 'LST' OPEN LST,T JRST HAVETT ; OPEN fails? Use TTY. OUTBUF LST,BUFNUM ; Got 'LST'. Set up buffers. SKIPA HAVETT: TXO F,F.TTY2 ; Use TTY as major output device. INBUF CMD,BUFNUM OUTBUF CMD,BUFNUM TXNN P1,DV.DIR ; Is 'LST' a directory device? JRST NOENTR ; No. Skip ENTER SKIPA T,[SIXBIT .RIP0.] ; Start with RIP0.LST MAKIT: ADDI T,010000 ; And inc to RIP1.LST , RIP2.LST etc CAMLE T,[SIXBIT .RIP9.] ; Quit after 10 tries. JRST EFAIL MOVSI T1,'LST' SETZB T2,T3 LOOKUP LST,T ; File already there? TRNE T1,-1 ; No. This is a good name JRST MAKIT ; Yes. Try another HLLZS T1 SETZB T2,T3 ENTER LST,T ; ENTER it. JRST MAKIT ; Can't. Try another name. NOENTR: MOVX T,%CNSTS ; Get configuration status word GETTAB T, SKIPA TXNN T,ST%TDS ; Must be level D JRST BADMON MOVEI M,IDRIP PUSHJ P,MSGTTY ; Must also introduce ourselves LDB N,VERPTR ; Get our major version # PUSHJ P,OCTPRT HRRZ N,.JBVER JUMPE N,ROLL PUSHJ P,LPAR HRRZ N,.JBVER PUSHJ P,OCTPRT ; 'RIPOFF V5(nnn)' ;Version and edit MOVEI CH,")" PUSHJ P,W.CMD ; Here to start the ball rolling... ROLL: PUSHJ P,CRLF MOVE P,PDP ; Reset the world SETZM ZROBEG ; Clear out data area MOVE T,[ZROBEG,,ZROBEG+1] BLT T,ZROEND ; This will work whether pure or not. MOV <[IOWD BLKSIZ,BUF]>,IOW ; Set up IOWD for I/O MOVI ^D8,RADIX ; Assumed radix is octal MOVSI T,DLST ; Get LST DEVNAM T, ; Get physical name SETZ T, ; No ASS DEV LST CAME T,[SIXBIT/DSK/] ; Was it ASS DSK LST? JRST ROLL1 ; Nope MOVEI T,T1 ; Point to block SETO T1, ; Return first str in search list MOVE T2,OURPPN ; for our PPN JOBSTR T, ; Get it SETZ T1, ; What can we do? MOVE T,T1 ; Get device name ROLL1: MOVEM T,LSTDEV ; Save list device MOVE T,[XWD 3,T1] ; SETOM T1 ; To read default path PATH. T, ; Do it SKIPA T,T1 ; T unchanged if no SFD's SETZ T, ; SETCAM T,%FTSFD ; =-1 if SFD's, 0 otherwise JUMPN T,ROLL2 ; If no SFD's in monitor MOVX T,%LDSFD ; GETTAB T, ; Get SFDLVL from monitor SETZ T, ; CAIE T,SFDLVL ; Better be equal to what wer're JRST BADCFG ; configured for ROLL2: MOVX T,%CNOPR GETTAB T, ; Find operators TTY name MOVSI T,DCTY ; (CTY) MOVEM T,DEVOPR MOVSI T,-6 ; We need 6 PPN's GETPP: MOVE T1,[%LDMFD %LDSYS %LDFFA %LDHLP %LDQUE %LDCRP](T) ; Pointers to necessary PPN's GETTAB T1, ; Ask monitor MOVE T1,[1,,1 1,,4 1,,2 2,,5 3,,3 10,,1](T) MOVEM T1,VIPS(T) ; and remember it. AOBJN T,GETPP ; Go for next PPN. MOVX T,%LDSTP GETTAB T, ; Standard protection MOVSI T,DPRT ; (155) MOVEM T,STNPRT MOVX T,%LDUFP GETTAB T, ; Standard UFD protection MOVSI T,DUFD ; (700) MOVEM T,UFDPRT MOVX T,%LDQUS GETTAB T, ; STR for QUEPPN queueing MOVX T,STRQUE ; Assume something MOVEM T,QUESTR SETOM WMASK ; Start out with /W mask = -1 SETZ T1, ; Figure out what machine we have.. MOVNI T,1 AOBJN T,.+1 JUMPN T,XKA BLT T,0 JUMPE T,XKI XKL: AOS T1 XKI: AOS T1 XKA: MOVEM T1,CPUXX ; 0=KA,1=KI,2=KL. MOVX T,%CNPGS GETTAB T, ; Get unit of core allocation MOVE T,[.SUAKA .SUAKI .SUAKL] (T1) MOVEM T,COREXX PUSHJ P,STRTUP ; Get startup option from user PUSHJ P,SYSINI ; Now we go initialize the world of disks SUBTTL Command scanner and dispatcher SCAN: SETZM CMDBEG ; Zero everything MOVE T,[CMDBEG,,CMDBEG+1] BLT T,ZROEND MOVE P,PDP ; Make sure PDL is clean MOVI SFDLVL,CMDLVL ; Assume full path ANDI F,F.TTY2 ; Start with no flags (except F.TTY2 if set) TXO F,STNDRD ; and defaults bits (all stars) TTYON ; and turn on TTY I/O SETZ SW, ; No switch options seen yet SKPINL ; Defeat ^O JFCL PUSHJ P,CRLF MOVEI CH,"*" PUSHJ P,W.CMD ; and start with the standard star OUTPUT CMD, PUSHJ P,GETCMD ; Get the command PARSE: PUSHJ P,RDATOM ; Get a name from CMD string TXZA F,.BCHR ; No break char read now PARSE2: TXO F,.BCHR ; Enter here if 'CH' has break char MOVSI T,-DISLEN ; Length of dispatch table HLRZ T1,DISPTB(T) ; Search through table CAME T1,CH ; for a match to the term char AOBJN T,.-2 HRRZ T,DISPTB(T) ; Match found (or table exausted) JRST (T) ; Dispatch on it DISPTB: XWD Z ,SWIT XWD <":"> ,FILDEV XWD <"."> ,FILDOT XWD <"["> ,FILPPN XWD <"/"> ,SWIT XWD <"_"> ,EQL XWD <"<"> ,TWOARG XWD <">"> ,TWOARG XWD <"="> ,EQL XWD <"("> ,FILREL XWD <"!"> ,RUNUUO DISLEN== .-DISPTB JRST CMDERR ; Falls through to here if illegal break char. ; Here when word ends in colon. FILDEV: TXNN F,.DOT ; Dot already seen? TXOE F,.COLON ; No. How abot colon? JRST CMDERR ; Yes. Illegal MOVEM M,USRSTR ; No. Must be a device name JRST PARSE ; Here on left arror or equal sign (equivalent). ; Single equal is an output device, double is assignment for /E cmds. EQL: MOVE T,CMDB ; Get CMD string pointer ILDB CH,T ; Look ahead to next char CAIE CH,"=" ; Double equal (_= would work too...) JRST FILDST ; No. Single. Output file preceeded. MOVEM T,CMDB ; Yes. Skip past character JRST NEWARG ; and get /EC args. FILDST: PUSHJ P,WHAT MOV USRSTR,AUXDEV ; Transfer stuff to output side.. MOV USRNAM,AUXNAM MOV USREXT,AUXEXT MOVI AUXPTH,AUXPPN ; Setup pointer to block MOVPTH USRPTH,AUXPTH MOV BARG3,AUXTRY SETZM USRSTR SETZM PTHFLG ; Used only for input path ANDI F,F.TTY2 TXO F,STNDRD JRST PARSE ; Here when name ends in a dot, must be a file. FILDOT: TXOE F,.DOT ; Dot already seen? JRST CMDERR ; Yes. Can't have two MOVEM M,USRNAM ; Must be a file name JRST PARSE ; Here when name ends in "[", find out what preceeds, and continue ; To read a project ,, programmer number (and maybe a path). FILPPN: PUSHJ P,WHAT ; Put last word where it belongs ( file or ext) TXO F,.LBRKT ; Remember the left bracket TXZ F,S.SFD ; Clear all SFD's flag SETZM CMDLVL ; Assume no SFD's typed in path PUSH P,RADIX ; Save input radix MOVI ^D8,RADIX ; Make it octal for now PUSHJ P,RDNUMR ; Get an octal proj,prog number POP P,RADIX ; Restore radix TLNN M,400000 ; RDNUMR see a star? TXZ F,S.PROJ ; No. No star TRNN M,400000 ; Same question? TXZ F,S.PROG ; Same answer MOVEM M,USRPTH+.PTPPN ; Save PPN in block CAIN CH,"," ; Start of SFD spec? SKIPN %FTSFD ; and monitor has SFD's? SKIPA ; Nope to one of the above PUSHJ P,FILPTH ; Yep CAIN CH,"]" ILDB CH,CMDB ; Allow optional closing bracket JRST PARSE2 ; Done. Now get next cmd string arg ; Here to process an SFD spec. Store the PPN at USRPTH+.PTPPN ; and the SFD names starting at USRPTH+.PTPPN+1. Insure no more ; than SFDLVL SFD's. Block is initially zero, so we ; don't have to worry about the terminator. FILPTH: SETOM PTHFLG ; Set have path flag MOVSI T1,-SFDLVL ; Build AOBJN word to insure no HRRI T1,1 ; more than SFDLVL names FLPTH1: PUSHJ P,RDWORD ; Get next atom from cmd string SKIPN M ; Gotta be non-null PJRST [POP P,(P) ; fixup stack JRST CMDERR ]; and tell user MOVEM M,USRPTH+.PTPPN(T1) ; Store in correct word in block XOR M,['* '] ; Was it a star? SKIPE M ; Yep, skip SETOM M ; Nope, set M to -1 for next instr SETCAM M,SFDFLG(T1) ; =0 if no star, -1 if star AOS CMDLVL ; Bump path level by one CAIN CH,"," ; More to come? AOBJN T1,FLPTH1 ; Loop if we don't have too many POPJ P, ; and go finish up ; Here to establish what preceeding argument was when it doesn't ; end in anything which gives automatic clue. (i.e., a colon tells ; us a dev probably predeeded, a dot says a file name, but a "[" or ; a "/" or line delimiter says nothing.. WHAT: TXNE F,.LBRKT!.BCHR ; Seen a "[" POPJ P, ; Yes. To late to be a file name or ext. CAIE P4,$CMBLK ; Block argument? JRST WHAT1 ; No. MOVEM M,BARG1 ; Yes. Remember it SETOM GOTWRD ; Also set flag for /ET MOVEI T,1 TXZE F,.LBS ; Pound sign? ORM T,BARGFL ; Yes. Set BARG flag POPJ P, WHAT1: TXNE F,.DOT ; Seen a dot? JRST FDOT ; Yes. MOVEM M,USRNAM ; No. Must be a file name POPJ P, FDOT: MOVEM M,USREXT ; Dot already seen, must be an extension here TXO F,.EXT ; Remember it POPJ P, ; Here when "(" recieved, input a relative block size FILREL: PUSHJ P,WHAT ; Identify previous arg PUSHJ P,RDATOM ; Read a number now CAIE P4,$CMBLK ; Must be numeric JRST CMDERR MOVEM M,BARG3 ; Save it for relative file size CAIN CH,")" ILDB CH,CMDB ; Allow closing paren JRST PARSE2 ; Here if "<" typed, input two block args TWOARG: CAIE P4,$CMBLK ; Better be a block arg JRST CMDERR MOVEM M,BARG1 SETOM GOTWRD ; Set flag for /ET MOVEI T,1 TXZE F,.LBS ORM T,BARGFL PUSHJ P,RDATOM ; Read next arg CAIE P4,$CMBLK JRST CMDERR MOVEM M,BARG2 MOVEI T,2 TXZE F,.LBS ORM T,BARGFL JRST PARSE2 ; Here on "==", /E edit args NEWARG: CAIE P4,$CMBLK ; First is a number and should look like block arg JRST CMDERR MOVEM M,BARG1 PUSHJ P,RDATOM ; Next can be any type of legal atom MOVEM M,BARG2 JRST PARSE2 ; Here when file name ended with "!" , do a RUN UUO to another program RUNUUO: PUSHJ P,WHAT PUSHJ P,KILL ; Fin all listing files SKIPN T,USRSTR MOVSI T,DSYS ; Defaults to sys SKIPN T1,USRNAM JRST CMDERR ; Must have a name! HLLZ T2,USREXT MOVE T4,USRPTH+.PTPPN RUNCOM: SETZB T3,T4+1 MOVEI T RUN ; and run it HALT RIPOFF ; Should never return here ; Here to take care of our many varieties of switches SWIT: PUSHJ P,WHAT ; Establish file or extension MOVSI T,'* ' CAME T,USRNAM ; Is the file name a star? SKIPN USRNAM ; Or no name at all? SKIPA ; Yes. Leave star bit set. TXZ F,S.NAM ; No. Zero star bit TXNE F,.DOT ; If no dot, cant have * ext. CAMN T,USREXT ; If dot, ext must be typed '*' SKIPA ; If he typed a star, leave star bit TXZ F,S.EXT ; He typed a dot and didnt follow star TXZ F,<.COLON!.DEV!.DOT!.EXT!.LBRKT!.LBS!F.TTY> SKIPN T,USRSTR ; If he typed a str, better check it. JRST SWT1 PUSHJ P,DEVTYP ; See if its AOK JUMPL T1,NOSTR ; Not a str. Cmd error.. MOVEM T1,TTYTYP ; Remember the type he typed MOVEM U,TTYDDB ; and unit 0 address SWT1: MOVSI T,'UFD' ; Zero above bits (no longer needed) CAME T,USREXT ; Is extension a 'UFD'? JRST SWT4 ; No. MOVE T,MFDPPN ; Yes. Then make 1,1 the SKIPN USRPTH+.PTPPN ; PPN by default MOVEM T,USRPTH+.PTPPN TXZ F,S.PROJ!S.PROG ; and forget we ever saw a PPN SWT4: MOVI USRPTH,USRPPN ; Setup pointer to path block TXOE F,S.SFD ; If flag is zero, a path JRST SWT3 ; was typed. Loop through MOVEI T,SFDLVL ; all levels to determine if SWT2: SKIPN SFDFLG(T) ; they are all stars. If so, TXZA F,S.SFD ; re-set the flag SOJG T,SWT2 SWT3: MOV USRNAM,TTYNAM ; Set up TTYNAM,EXT,PPN MOV USREXT,TTYEXT ; so routines can retrieve MOV USRPPN,TTYPPN ; incase they destroy names. MOVPTH USRPTH,TTYPTH JRST RIPDON ; Don't try to restore core ; ; ; Return here when all done with a switch processing routine. ; RIPDN1 to restore the contents of .JBFF from .SVFF ; RIPDON in the normal case RIPDN1: PUSHJ P,ZCORE ; Restore .JBFF from .SVFF RIPDON: OUTPUT CMD, ; Flush the TTY buffer TXNN F,F.TTY2 ; Writing a listing file too? OUTPUT LST, ; Yes, flush that too PUSHJ P,RLSDSK ; Release all channels SETOM STRFLG ; Initialize for NXTSTR HRRZS UNIDDB ; Kill links for current STR ; Here to read next switch char in CMD string and set options bits ; in AC "SW". NXTSWT may be called at any time NXTSWT: AND F,[STNDRD!F.TTY2] ; Zero all but inportant bits MOV TTYNAM,USRNAM ; Make names right so MOV TTYEXT,USREXT ; anybody that screws them MOV TTYPPN,USRPPN ; wont hurt next routine. MOVPTH TTYPTH,USRPTH SETZB SW,P1 ; Start with no options or switches JSP M,CHRGET ; Get first switch char MOVE P1,CH ; and save it in P1 NXTSW0: JSP M,CHRGET ; Now read options CAIN CH,"/" JRST SWITGO ; Done for now.. CAIL CH,"0" CAILE CH,"9" JRST NXTSW1 SUBI CH,"0"-^D26 ; Char is numeric, goes in bits 26-35 NXTSW2: MOVEI T,1 LSH T,(CH) ; Make T=Bit for this switch ORM T,SW ; and add it to the list JRST NXTSW0 NXTSW1: CAIL CH,"A" ; If not numeric, must be alphabetic CAILE CH,"Z" JRST BADSW ; Not either, hes a dummie SUBI CH,"A" ; For alpha chars, A=Bit 35, B=34, etc JRST NXTSW2 CHRGET: ILDB CH,CMDB ; Read a char JUMPE CH,SWITGO CAIE CH,.CHTAB ; Ignore tabs/spaces CAIN CH," " JRST CHRGET CAIE CH,";" ; Ready for a comment? JRST (M) ; No. Return ILDB CH,CMDB ; Yes. Ignore rest of CMD string JUMPN CH,.-1 ; Here to finally go dispatch to switch routines SWITGO: JUMPE P1,SCAN ; No switches typed, ignore CMD CAIL P1,"A" CAILE P1,"Z" JRST BADSW ; Switches may be alphabetic only SUBI P1,"A" JUMPE SW,SWITG1 ; If no option, must be OK! HRRZ T,SWTAB(P1) ; Address of legal options JUMPE T,ERR001 ; Unless zero MOVE T1,SW ; T1=switches he gave us ANDCM T1,(T) ; Turn off all legal switches JUMPE T1,SWITG1 ; Should leave us with nothing JRST ERR001 ; Bad option SWITG1: HLRZ T,SWTAB(P1) ; Address of routine JRST (T) ; Go! ; Table of switches and their legal options ; Format is: ; ; XWD Addr of routine,,Addr of legal switch bits ; SWTAB: SWT.A ,, [CH.X!CH.T!CH.M!CH.F!CH.E] BADSW ,, SWT.C ,, [CH.U!CH.T!CH.P!CH.D!CH.C!CH.B] SWT.D ,, [CH.A!CH.U!CH.T!CH.R!CH.N!CH.M!CH.B] SWT.E ,, [CH.7!CH.6!CH.W!CH.U!CH.T!CH.S!CH.R!CH.N!CH.L!CH.C!CH.A] SWT.F ,, [CH.2!CH.D!CH.E] BADSW ,, SWT.H ,, [-1] SWT.I ,, [CH.2!CH.X!CH.T!CH.S!CH.R!CH.P!CH.O!CH.F!CH.E!CH.D!CH.A] BADSW ,, BADSW ,, SWT.L ,, [CH.U] BADSW ,, BADSW ,, BADSW ,, 0 SWT.P ,, [CH.6!CH.7!CH.V!CH.U!CH.S!CH.R!CH.Q!CH.P!CH.O!CH.L!CH.F!CH.E!CH.D!CH.B!CH.A] BADSW ,, SWT.R ,, 0 SWT.S ,, [CH.W!CH.T!CH.R!CH.P!CH.M!CH.L!CH.F!CH.B] BADSW ,, SWT.U ,, 0 SWT.V ,, [CH.Q!CH.F!CH.A] SWT.W ,, [CH.M!CH.S!CH.T!CH.W] SWT.X ,, [CH.Q] BADSW ,, BADSW ,, SUBTTL Switch processing routines REPEAT LOGIC,< Switches are- /A - Alphabatize UFD's (sort them by PPN if MFD, or files) /C - Convert disk parameters /D - Delete /E - Edit disk blocks /F - Find files /H - Help /I - Initialize UFD or files from RIBs only /L - Lock in core /P - Print according to format /R - Read verify blocks /S - Play with SATs, STRUUO's /U - Make a UFD/SFD /V - Verify files and fix SATs /W - Do word searches on disk /X - Close listing and exit > SUBTTL /A -- Alphabatize UFD's/SFD's... REPEAT LOGIC,< /A Options include: /AF - Sort by file names and extensions (standard) /AE - Sort by extensions and names /AT - Sort by creation time and date (oldest first) /AM - Sort the MFD only (/AF,/AE,/AT will not sort MFD) X - X option OR'ed with above suppresses printout > SWT.A: PUSHJ P,NONAME ; Command is *[P,PN]/A JRST ERR002 MOVSI T,(CAMN T,0) ; On all sorts, we avoid the MFD TXNE SW,CH.M ; except on M option, in which case MOVSI T,(CAME T,0) ; we avoid everything but the MFD HRRI T,MFDPPN ; Make an instruction word MOVEM T,ATEST ; XCT ATEST to decide whether to sort this guy. MOVEI T,0 ; Assume F option TXNE SW,CH.E MOVEI T,1 TXNE SW,CH.T MOVEI T,2 MOVEM T,LHEAD+1 ; This is key for sort. MOVEI T,2 TXNE SW,CH.T MOVEI T,3 ; 2 word entries for all but /AT MOVEM T,LHEAD ; which has 3. Store in LHEAD. TXNE SW,CH.X ; Supress messages? JRST SWT.A0 ; Yes. Supress them. MOVEI M,[ASCIZ/ Directories sorted: /] PUSHJ P,MSGTTY ; Give him a heading SWT.A0: MOV .JBFF,.SVFF ; Save core limits now SWT.A1: PUSHJ P,NXTSTR ; Get next structure JRST RIPDN1 ; No more, restore core and return JRST PNOMFD ; Tell of no MFD and quit TXNN SW,CH.M ; /AM specified for this STR? JRST SWT.A2 ; No PUSHJ P,STRMNT ; This STR mounted? JRST ERR016 ; Yes, can't do this SWT.A2: PUSHJ P,NXTDIR ; Get next directory JRST SWT.A1 ; None left, try next STR MOVE T,USRPTH+.PTPPN ; Get PPN of candidate XCT ATEST ; Shall we sort him? JRST SWT.A2 ; No TXO F,F.NULL ; Assume directory is null SWT.A3: PUSHJ P,NXTFIL ; Get next file. JRST SWT.A5 ; EOF, go sort directory TXZ F,F.NULL ; No longer null TXNN SW,CH.T ; Need to find creation time? JRST SWT.A4 ; No. Good. PUSHJ P,USRLOK ; Yes. Look up file SKIPA T3,ZERO ; Oh well, use zero PUSHJ P,FILDAT ; Get date,,time in T3 MOVE P1,T3 ; and save time in P1 SWT.A4: MOVE T,LHEAD PUSHJ P,CORGRB ; Get some core MOVE T1,USRNAM MOVEM T1,(T) ; Store name HLLZ T1,USREXT ; Second word is EXT,, HRR T1,USRCFP ; CPF MOVEM T1,1(T) TXNE SW,CH.T ; Sort by time? MOVEM P1,2(T) ; Yes. Store time word too. JRST SWT.A3 ; and repeat for all files ; Here when all files for the current level are in core. ; SWT.A5: TXNE F,F.NULL ; Null directory? JRST SWT.A7 ; Yes, sort is done MOVE T,.SVFF ; Get address of 1st word to sort MOVE T1,LHEAD+1 ; Key for sort. MOVE N,.JBFF ; Add of last word +1 MOVEM N,SORTOP ; Remember this for later SUBI N,(T) ; # of words to sort MOVE CH,LHEAD ; Length of entries IDIVI N,(CH) ; N=# of entries PUSHJ P,SORT ; Go sort it all ; Here when UFD sorted. Now get ready to write it back out. MOVE P4,CURLVL ; Get current level MOVE P4,CORBLK(P4) ; Point to correct core block MOVE T,FNAME(P4) ; Get filename MOVE T1,FEXT(P4) ; and extension MOVE T2,FCFP(P4) ; Get CFP MOVEI T3,FPATH(P4) ; Point to path PUSHJ P,ENTR ; Do an enter on his UFD/SFD JRST SWT.A9 ; Shouldn't fail ; Here when the directory is sorted to write it back out ; MOVE T,.SVFF ; Get address of first word SWT.A6: MOVE CH,0(T) ; Get a word from new UFD PUSHJ P,W.UFD ; and write it back over old one JRST SWT.A9 MOVE CH,1(T) PUSHJ P,W.UFD JRST SWT.A9 ADD T,LHEAD CAMGE T,SORTOP ; Done? JRST SWT.A6 ; No. Keep writing PUSHJ P,C.UFD ; Done. Now close the file. MOV .SVFF,.JBFF ; Restore core SWT.A7: TXNE SW,CH.X JRST SWT.A2 TTYON PUSHJ P,CRLF SWT.A8: PUSHJ P,UFDPNT ; Print success story JRST SWT.A2 ; and return SWT.A9: MOVEI M,[ASCIZ/ Failure on sort of /] PUSHJ P,MSGTTY JRST SWT.A8 U(ATEST) ; CAMX T,MFDPPN U(SORTOP) ; Top of core to sort SUBTTL /C -- Convert disk parameters ; ; Accept a block, cluster, CFP, or cylinder, surface, and sector ; and convert them to other pertinent values. Options include: ; ; /CB - Convert block number in structure ; /CC - Convert cluster number in structure ; /CD - Convert CFP ; /CP - Convert cylinder, surface, and sector ; /CT - Convert universal date/time (Not exactly a disk parameter ; but a useful conversion anyway) ; /CU - Convert block number in unit SWT.C: TTYON ; All output goes to the TTY MOVE T,TTYTYP ; Get device type specified CAIE T,$DVSTR ; Must be a STR TXNE SW,CH.P!CH.U!CH.T ; unless /CP or /CU or /CT specified SKIPA ; All ok JRST ERR017 ; Bad device PUSHJ P,NXTSTR ; Setup for this structure JRST RIPDON ; Nothing there? JFCL ; No MFD is OK ; ; Here to process the /CC option. Convert the cluster number to, and ; print the corresponding block range and CFP in the structure, and ; the unit number, block range, and physical position on the unit. ; TXNN SW,CH.C ; /CC option specified JRST SWT.C1 ; No MOVEI M,[ASCIZ/Cluster /] PUSHJ P,PREFIX ; Print prefix and cluster number PUSHJ P,STRPFX ; Print structure line prefix MOVE P1,BARG1 ; Get the cluster number IMUL P1,STRBPC ; Convert to block number MOVE N,P1 PUSHJ P,CLSBLK ; Print range of blocks MOVE N,P1 ; Get block number back PUSHJ P,CFPPFX ; Print CFP MOVE P2,P1 ; Don't destroy P1 IDIV P2,STRBPU ; Convert to unit, block on unit MOVE N,P2 ; Get unit number PUSHJ P,UNIPFX ; Print unit MOVE N,P3 ; Get block on unit PUSHJ P,CLSBLK ; Print range on unit PUSHJ P,CRLF ; End the line PUSHJ P,TAB2 ; Followed by 2 tabs MOVE T2,P3 ; Get block on unit PUSHJ P,PBNPRT ; Print disk address of first block MOVEI M,[ASCIZ/ through /] PUSHJ P,MSGTTY ; Put out separator MOVE T2,P3 ; Get first block back ADD T2,STRBPC ; Compute last block+1 SUBI T2,1 ; Compute last block PUSHJ P,PBNPRT ; Print physical address of last block JRST SWT.C5 ; Go finish up ; ; Here to process the /CB switch. Convert the block number to the ; cluster, relative block, and CFP in the structure, and the block, ; and cylinder, surface, and sector on the unit. ; SWT.C1: TXNN SW,CH.B ; Was /CB specified? JRST SWT.C2 ; No MOVEI M,[ASCIZ/Block /] PUSHJ P,PREFIX ; Print prefix and block number PUSHJ P,STRPFX ; Print structure prefix MOVE P2,BARG1 ; Get the block number IDIV P2,STRBPC ; Convert to cluster, relative block MOVE N,P2 PUSHJ P,CLSPFX ; Print the cluster number MOVE N,P3 ; Get the relative block in cluster PUSHJ P,RLBPFX ; Print that also MOVE N,BARG1 ; Get the block number back PUSHJ P,CFPPFX ; Print the CFP MOVE P1,BARG1 IDIV P1,STRBPU ; Convert to unit, block on unit MOVE N,P1 PUSHJ P,UNIPFX ; Print the unit MOVE N,P2 ; Get the block on unit PUSHJ P,BLKPFX ; Print that also MOVEI M,[ASCIZ/, /] PUSHJ P,MSGTTY ; Print separator MOVE T2,P2 ; Get block on unit PUSHJ P,PBNPRT ; Print physical address JRST SWT.C5 ; Go finish up ; ; Here to process the /CD option. Convert the CFP to, and print, ; the block and cluster on the structure, and the block and ; cylinder, surface, and sector on the unit. ; SWT.C2: TXNN SW,CH.D ; Was /CD specified? JRST SWT.C3 ; No MOVEI M,[ASCIZ/CFP /] PUSHJ P,PREFIX ; Print prefix and CFP PUSHJ P,STRPFX ; Print structure prefix MOVE P1,BARG1 ; Get the CFP IMUL P1,HOMBSC(U) ; Convert to block number MOVE N,P1 PUSHJ P,BLKPFX ; Print the block number MOVEI M,[ASCIZ/, /] PUSHJ P,MSGTTY ; Output separator MOVE N,P1 ; Get the block back IDIV N,STRBPC ; Convert to cluster number PUSHJ P,CLSPFX ; and print it IDIV P1,STRBPU ; Convert to unit, block on unit MOVE N,P1 ; Get the unit number PUSHJ P,UNIPFX ; Print the unit number MOVE N,P2 ; Get the block on the unit PUSHJ P,BLKPFX ; Print that also MOVEI M,[ASCIZ/, /] PUSHJ P,MSGTTY ; Print separator MOVE T2,P2 ; Get block on unit again PUSHJ P,PBNPRT ; Print physical disk address JRST SWT.C5 ; Go finish up ; ; Here to proces the /CU option. Convert the block to the cylinder, ; surface, and sector. ; SWT.C3: TXNN SW,CH.U ; Was /CU specified? JRST SWT.C4 ; No MOVEI M,[ASCIZ/Block /] PUSHJ P,PREFIX ; Print prefix and block number MOVEI M,[ASCIZ/ on unit Unit: /] PUSHJ P,MSGTTY MOVE T2,BARG1 ; Get block on unit PUSHJ P,PBNPRT ; Print physical disk address JRST SWT.C5 ; Go finish up ; ; ; Here to process the /CP option. Convert the cylinder, surface, ; and sector to a block on the unit ; SWT.C4: TXNN SW,CH.P ; Was /CP specified? JRST SWT.C6 ; No MOVE P1,BARG1 ; Get cylinder IMUL P1,BLKCYL(U) ; Compute offset to this cylinder MOVE P2,BARG2 ; Get surface IMUL P2,BLKTRC(U) ; Compute offset from last cylinder ADD P1,P2 ; Compute address of start of surface ADD P1,BARG3 ; Add in sector address MOVE T2,P1 PUSHJ P,PBNPRT ; Print the address MOVEI M,[ASCIZ/ Unit: /] PUSHJ P,MSGTTY MOVE N,P1 ; Get the block number PUSHJ P,BLKPFX ; Print the block SWT.C5: PUSHJ P,CRLF ; End with CRLF PJRST RIPDON ; Go do next command ; ; ; Here to process the /CT option. Print the universal date/time ; in a readable format. ; SWT.C6: TXNN SW,CH.T ; Was /CT specified? JRST ERR001 ; No, bad option MOVE N,BARG1 ; Get universal date/time PUSHJ P,DATTIM ; Print it JRST SWT.C5 ; Go finish up SUBTTL /D -- Delete files. ; /D Options include: ; ; /D Delete specified files ; /DB Delete file only if it is bad (according to monitor) ; /DT Ask for time criteria; Only delete files created before specified ; creation date, or not accessed since specified access date. ; /DU Delete all files of given PPN and then delete UFD too ; (i.e., wipe him out) ; /DN Delete all null directories within specified PPN's ; /DR OR'ed with above options, but uses RIPOFF delete ; (RIPFIL). SATs guaranteed to be messed up. ; Much faster however. ; /DA OR'ed with above options causes RIPOFF to print filename ; and ask for confirmation of every file to be deleted. ; Does not apply to N or U options. ; /DM OR'ed with above options causes RIPOFF to use only the monitor ; RENAME when deleting files. SWT.D: SETCM T,F TXNN T,STNDRD ; *.*[*,*]/D ?? PUSHJ P,ASK003 ; More likely a mistake...! TXNN SW,CH.U ; Was /DU specified? JRST SWT.D6 ; No SKIPG CMDLVL ; Skip if any SFD's typed in cmd string TXO F,S.SFD ; [p,pn]/DU implies [p,pn,*,*,*,*,*]/du TXNN F,S.SFD ; If SFD's specified, were they all "*"? JRST ERR018 ; No, can't do that SWT.D6: TTYON PUSHJ P,CRLF TXNN SW,CH.T ; Time options? JRST SWT.D4 ; No. Skip this MOVEI M,[ASCIZ/Delete if created before: /] PUSHJ P,MSGTTY OUTPUT CMD, PUSHJ P,GTDATE ; Input time and date MOVEM T3,BEFORE ; and save in handy place MOVEI M,[ASCIZ/and not accessed since: /] PUSHJ P,MSGTTY OUTPUT CMD, PUSHJ P,GTDATE MOVEM T3,AFTER ; Store. MSTIME T1, ; Get current time DATE T2, ; and date PUSHJ P,.CNVDT ; in 36 bits MOVE T4,AFTER TLNN T4,-1 ; Did he not give a date? HLLM T3,AFTER ; Use now MOVE T4,BEFORE TLNN T4,-1 HLLM T3,BEFORE SWT.D4: TXNN SW, ; Can't specify filenames for /DU or /DN JRST SW.D4A ; None of these options PUSHJ P,NONAME ; Check it out JRST ERR002 ; Can't do that fella ; Here to start the search for files to be deleted SW.D4A: TXNE SW,CH.M ; /DM specified? TXOA F,F.MDEL ; Yes, set flag for DELFIL TXZ F,F.MDEL ; Otherwise, clear the flag TXNN SW,CH.U ; Now decide what header to type SKIPA M,[[ASCIZ/Files deleted:/]] MOVEI M,[ASCIZ/Deleting all files for users:/] TXNE SW,CH.N MOVEI M,[ASCIZ/Deleting null directories, users:/] PUSHJ P,MSGTTY PUSHJ P,CRLF SW.D0A: PUSHJ P,NXTSTR ; Get next STR JRST RIPDON ; When through JRST PNOMFD ; Gotta have an MFD SWT.D0: MOVEI M,NXTDIR ; Default is to call NXTDIR TXNE SW,CH.U ; Unlesss /DU specified MOVEI M,NXTPPN ; In which case, use NXTPPN PUSHJ P,(M) ; Call one or the other JRST SW.D0A ; All done, try next STR TXZ F,F.NULL ; Flag says first time through SWT.D1: PUSHJ P,NXTFIL ; Get next file from directory JRST SWT.D2 ; At end of directory TXNN SW,CH.T ; /DT?? JRST SWT.D5 ; No, no need to LOOKUP file PUSHJ P,USRLOK ; LOOKUP file to get dates JRST SWT.D1 ; Ignore if cant PUSHJ P,FILDAT ; Get T3 = creation date CAML T3,BEFORE ; Created since input creation time JRST SWT.D1 ; Yes. Ignore it PUSHJ P,FILACD ; Get T3 = access date CAML T3,AFTER ; Last access date before then? JRST SWT.D1 ; Yes. Ignore it SWT.D5: TXNE SW,CH.N ; Deleting null directories? JRST SWT.D0 ; Yes. This ones not null, forget it. TXOE F,F.NULL ; First file? JRST SWT.D3 ; No PUSHJ P,CHKPPN ; He important guy?? JRST SWT.D0 ; Hell yes! TXNE SW,CH.U ; /DU?? JRST SW.D3A ; Yes. Dont print every file MOVEI M,[ASCIZ/ From /] PUSHJ P,MSGTTY ; /D gets a header for each user MOVE M,USRSTR ; Get structure name PUSHJ P,PR6BIT ; Print it PUSHJ P,COLON ; Followed by a colon PUSHJ P,UFDPNT ; Print directory path PUSHJ P,CRLF ; Here when a file found that matches the command string SWT.D3: TXNN SW,CH.U ; /DU doesn't have ask mode TXNN SW,CH.A ; Ask mode? JRST SW.D3A ; No TXO F,F.NOTB ; Print name with dot, not tab PUSHJ P,FILPNT ; Print the filename MOVEI M,ZERO ; No message for OPER PUSHJ P,OPER ; Ask him JRST SWT.D1 ; Doesn't want to delete this one SW.D3A: TXNE SW,CH.B ; Only bad files? TXOA F,F.DBAD ; Yes. Set bit to tell DELFIL TXZ F,F.DBAD MOVEI T,DELFIL ; Get set to delete the file TXNE SW,CH.R ; Super delete? MOVEI T,RIPFIL ; Yes. PUSHJ P,(T) ; Go delete this one. JRST SWT.D1 ; Ignore it if cant TXNE SW,CH.U JRST SWT.D1 TTYON ; Print name of all files deleted TXO F,F.NOTB ; Use dot instead of tab PUSHJ P,FILPNT PUSHJ P,TAB MOVSI M,(SIXBIT .<>.) SKIPGE UBLKCT ; Get number of blocks deleted PUSHJ P,PR6BIT ; Print <> if dont know SKIPL N,UBLKCT PUSHJ P,DECPRT ; Otherwise, tell him PUSHJ P,CRLF JRST SWT.D1 ; Here if no more files in current directory SWT.D2: TXNN SW, JRST SWT.D0 ; Done if plain /D PUSHJ P,CHKPPN ; Important guy again? JRST SWT.D0 ; Yup. PUSHJ P,DELUFD ; Otherwize, delete the UFD now. JRST SWT.D0 TTYON MOVE M,USRSTR ; Get structure name PUSHJ P,PR6BIT ; Print it PUSHJ P,COLON ; followed by a colon PUSHJ P,UFDPNT ; and finally the directory PUSHJ P,CRLF JRST SWT.D0 SUBTTL /E -- Edit disk blocks REPEAT LOGIC,< /E options include C,L,N,R,S,W,T,A,6. /ER - Read given block into core /EW - Write core block out to given disk block /EC - Change core copy of block /ET - Type contents of given word in octal /ETA or /ET7 - Type contents of given word in ASCII /ET6- " " in SIXBIT code /ETU- " " as a universal date/time word /ERS OR /EWS- S option OR'ed with W or R will read or write same STR and same block number as the last /E operation. /ETL, /ETS, /ETN - L, S, or N option or'ed with the T option with no word specified will type the last, same, or next word (relative to the previous word). > SWT.E: SKIPE T,EBUF ; EBUF is ptr to data block JRST SWT.E1 ; Have pointer, will process TXNN SW,CH.R ; No ptr, better be reading JRST ERR005 ; Write or edit what?? MOVEI T,BLKSIZ ; Need this much core for data block PUSHJ P,CORGRB ; Grab enough core for our use MOVEM T,EBUF ; and remember where it is. ; Here to set up things for output or input SWT.E1: TXNN SW, ; Skip if reading or writing JRST SWT.E3 ; Go edit or type words SKIPE USRSTR ; Did he specify a STR? JRST SWT.E6 ; Yes. Use it. TXNN SW,CH.S ; No. 'S' option? JRST NOSTR1 ; No. Must specify a STR then. MOV ESTR,USRSTR ; With S option, fake a STR: PUSHJ P,DEVTYP ; in the command string by doing JUMPL T1,NOSTR ; the same thing scanner does MOVEM T1,TTYTYP ; at SWIT: MOVEM U,TTYDDB MOV EBLK,BARG1 ; Fake block number too ; Here to read or write the block specified by BARG1 on the structure ; specified by USRSTR. SWT.E6: PUSHJ P,NXTSTR ; Go init device JRST NOSTR ; Can't? JFCL ; Don't care if MFD or not MOVE T,USRSTR ; Get STR name MOVE T1,BARG1 ; and block number MOVEI P1,STRRED ; Assume reading TXNN SW,CH.W ; Writing? JRST SWT.E4 ; No. MOVEI P1,STRWRT ; Yes. Set for write. CAME T,ESTR ; Same STR as before? PUSHJ P,ASK001 ; No. Sure? CAME T1,EBLK ; Same block? PUSHJ P,ASK002 ; Check again. SWT.E4: MOVEM T1,EBLK ; Remember last block MOVEM T,ESTR ; and last device HRLZI T,-BLKSIZ HRR T,EBUF ; T=IOWD to buffer for block SOJ T, MOVEI P4,DSK ; Read on DSK channel TTYON ; Enable TTY output PUSHJ P,(P1) ; Go do it now. JFCL ; Error. Forget it. JRST RIPDON ; and thats it.. ; Here to edit the block (/EC) SWT.E3: TXNN SW,CH.C ; Editing? JRST SWT.E7 ; No, must be typing MOVE N,BARG2 ; Get new contents of word SKIPL T,BARG1 ; Make sure word to chage is in range CAIL T,BLKSIZ ; i.e. (0-177) JRST ERR006 ; No, tell him how big block is MOVEM T,EWORD ; Save as last word accessed ADD T,EBUF ; Make T pointer to word in core MOVEM N,(T) ; Change the word JRST RIPDON ; That's it ; Here to type the a word in the block in one of our several modes SWT.E7: TXNN SW,CH.T ; Must be typing or bad option JRST ERR001 ; No. Bad option TTYON ; Enable TTY output PUSHJ P,CRLF ; To make it look good SKIPE GOTWRD ; Word specified in command? JRST SWT.E8 ; Yes, ignore /ETL, /ETS, and /ETN MOVE T,EWORD ; Pick up last word used TXNE SW,CH.L ; Last word wanted? MOVEI T,-1(T) ; Yes, decrement the pointer TXNE SW,CH.N ; How about next one? MOVEI T,1(T) ; Then add one MOVEM T,BARG1 ; Save as word to use SWT.E8: SKIPL T,BARG1 ; T=which word of block to change CAIL T,BLKSIZ ; which must be 0-177 JRST ERR006 ; Ill block arg MOVEM T,EWORD ; Make this last word used ADD T,EBUF ; Make T a real core pointer PUSH P,T ; Save address for later MOVE N,BARG1 ; Get block index back MOVEI T,6 ; Field width to use PUSHJ P,OCTZRO ; Print index as an octal number PUSHJ P,SLASH ; Followed by a slash PUSHJ P,TAB ; Followed by a TAB POP P,T ; restore T MOVE N,(T) ; Get old contents TXNN SW,CH.A!CH.7 ; Type in ASCII? JRST SWT.ES ; No. SETZ N1, ; Yes. Make ASCIZ MOVEI M,N ; M=Address of word PUSHJ P,MSGTTY ; Type it JRST SWT.E5 ; Done. SWT.ES: TXNN SW,CH.6 ; SIXBIT? JRST SWT.EU ; No. Try universal date/time PUSHJ P,NPR6BT ; Yes. Print it in SIXBIT. JRST SWT.E5 SWT.EU: TXNN SW,CH.U ; universal date/time? JRST SWT.EO ; No, just octal PUSHJ P,DATTIM ; Print it JRST SWT.E5 ; Go finish up SWT.EO: PUSHJ P,OCTL12 ; Type contents in octal SWT.E5: PUSHJ P,CRLF ; End line with CRLF SKIPN T,BARG3 ; Have a non-zero increment? MOVEI T,1 ; No, use default of 1 ADDB T,BARG1 ; Bump index by increment CAMG T,BARG2 ; Larger than final value? JRST SWT.E8 ; No, loop for more JRST RIPDON SUBTTL /F -- Find files ; Find and print relative and logical block numbers of ; the RIB of a file. ; ; /F options include: ; ; /F - Find files. Try directory search first then structure ; search ; /FE - Find existing files, i.e., only do directory search ; /FD - Find deleted files, i.e., only do structure search ; /F2 - When OR'ed with /FD option, enables 2nd RIB searching SWT.F: TXNE SW,CH.D ; D switch specified? JRST SWT.F8 ; Yes, don't do lookups TXZ F,F.MULT ; Clear files found flag SWT.F1: PUSHJ P,NXTSTR ; Get next str JRST SWT.F4 ; None left, do search JRST SWT.F1 ; SWT.F2: PUSHJ P,NXTPPN ; Get next PPN JRST SWT.F1 ; None left SWT.F3: PUSHJ P,NXTFIL ; Get next file JRST SWT.F2 ; None left TXOE F,F.MULT ; Seen any before? JRST SWT.F7 ; Yep, don't print heading again MOVEI M,[ASCIZ/Files found in directories: /] PUSHJ P,MSG ; Print it SWT.F7: MOVE T,USRCFP ; Get CFP for this file PUSHJ P,CFP2BK ; Convert to blocks PUSHJ P,PRTFND ; Print the infor JRST SWT.F3 ; and get next one ; ; Here to do a search on the file structure looking for ; the RIBs of a file that matches the specifications. ; SWT.F4: TXZE F,F.MULT ; See any files in directories? JRST SWT.F8 ; Yep MOVEI M,[ASCIZ/% No files found in directories /] PUSHJ P,MSG ; SWT.F8: TXNE SW,CH.E ; E switch seen? JRST RIPDON ; Yep, we're done SETOM STRFLG ; To reset NXTSTR SWT.F5: PUSHJ P,NXTSTR ; Get next str JRST SWT.FD ; None left JFCL ; No MFD is OK SETZM SATFLG ; Search all blocks MOVN T4,STRBPC ; Get negative blocks/cluster TXNE SW,CH.2 ; Unless second RIB recovery MOVNI T4,1 ; In which case use -1 MOVEM T4,SETBLK ; This is starting block HLRZ U,UNIDDB ; Setup U for SEARCH SWT.F6: MOVEI P1,RIBCOD ; Keyword MOVEI P2,CODRIB ; Contents of keyword MOVE T4,STRBPC ; Search every cluster TXNE SW,CH.2 ; Unless second RIB recovery MOVEI T4,1 ; is enabled PUSHJ P,SEARCH ; Go find a block JRST SWT.F5 ; None left on this str MOVE T1,SETBLK ; TXO F,F.RIB ; Tell RIBCHK not to check names PUSHJ P,RIBCHK ; Is it a valid RIB? JRST SWT.F6 ; Nope, ignore it PUSHJ P,CHKMAT ; Is it ours? JRST SWT.F6 ; Nope ;;[77] At SWT.F6 + 14 1/2 MOVEM T,USRNAM ;[77] Correct name in case of wildcards MOVEM T1,USREXT ;[77] Correct extension in case of wildcards MOV BUF+RIBPPN,USRPTH+.PTPPN;[77] Correct PPN in case of wildcards TXOE F,F.MULT ; Seen any files yet? JRST SWT.F9 ; Yep MOVEI M,[ASCIZ/Files found via structure search: /] PUSHJ P,MSG ; SWT.F9: MOVE T1,SETBLK ; Block in unit MOVE T,HOMLUN(U) ; Get logical unit number IMUL T,STRBPU ; Times blocks/unit ADD T,T1 ; Give block in str PUSHJ P,PRTFND ; Print info JRST SWT.F6 ; and loop for next one SWT.FD: TXNE F,F.MULT ; See any files on search? JRST RIPDON ; Yep MOVEI M,[ASCIZ/% No files found via structure search /] PUSHJ P,MSG ; JRST RIPDON ; SUBTTL /H -- Type the RIPOFF help file SWT.H: MOVEI P1,MAXHLP-1 SWT.H1: MOVEI T,.IODMP ; Get it in dump mode MOVE T1,HLPTAB(P1) ; on one of several devices SETZ T2, OPEN STR,T JRST SWT.H3 MOVE T,['RIPOFF'] MOVSI T1,'HLP' SETZB T2,T3 LOOKUP STR,T JRST SWT.H3 SWT.H2: IN STR,IOW SKIPA M,[BUF] JRST RIPDON PUSHJ P,MSGTTY JRST SWT.H2 SWT.H3: SOJGE P1,SWT.H1 ; Try another device JRST ERR014 ; or give error message HLPTAB: SIXBIT .DSK. SIXBIT .SYS. SIXBIT .HLP. MAXHLP==.-HLPTAB SUBTTL /I -- Initialize UFD's from scratch REPEAT LOGIC,< SEE DOCUMENTION FOR OPERATION OF THIS SWITCH. ONE PASS IS MADE OVER THE ENTIRE FILE STRUCTURE. THE FIRST BLOCK OF EACH CLUSTER IS READ AND TESTED AS A RIB. ALL RIBS FOUND MATCHING THE COMMAND STRING SPECIFICATIONS AS TO FILE NAMES AND PPNS ARE REMEMBERED IN A CORE LINKED LIST. FOR EVERY PPN IS A TWO WORD BLOCK WHICH CONTAINS: WORD 0: ADDRESS NEXT PPN BLOCK ,, ADDRESS FIRST FILE BLOCK FOR THIS PPN WORD 1: PROJECT ,, PROGRAMMER NUMBER FOR EACH FILE IS KEPT A FOUR WORD BLOCK: WORD 0: FILE EXTENSION ,, ADDRESS NEXT FILE BLOCK THIS PPN WORD 1: FILE NAME WORD 2: CREATION DATE ,, CREATION TIME IN UNIVERSAL STANDARD (12 OR 15 BIT FORMATS CONVERTED TO UNIVERSAL STANDARD) WORD 3: BYTE (4) LOGICAL UNIT , BYTE (32) LOGICAL BLOCK NUMBER WITHIN UNIT OF FIRST RIB IF A FILE IS FOUND DUPLICATED ON THE STR (OLDER VERSIONS), THIS LIST IS CHECKED AND TESTED AGAINST THE CREATION DATE AND TIME. ONLY THE LATEST VERSION IS REMEMBERED. WHEN THE ENTIRE STR IS SEARCHED, THE TABLES ARE RESCANNED, AND THE RIB IS RE-READ. THE RIB IS OUTPUT TO A SCRATCH DEVICE (MAGTAPE, DECTAPE, OR SCRATCH PACK). THEN THE ENTIRE FILE IS READ AND OUTPUT TO THE SCRATCH STORAGE. ALL FILES ARE THUS TRANSMITTED TO THE AUXILLIARY DEVICE, ALONG WITH THEIR FIRST RIBS. THE SCRATCH AREA IS WRITTEN AS ONE CONTIGIOUS FILE. NOTE: IF A SCRATCH PACK IS USED, WRITING WILL BEGIN ON BLOCK ONE AND CONTINUE ON SUCCESSIVE BLOCKS. THUS, THE PACK WILL BE DESTROYED FOR USE AS A FILE STRUCTURE, AND WILL NEED TO BE REFRESHED AFTER USE. WHEN ALL FILES ARE TRANSMITTED TO SCRATCH, THE DEVICE MAY BE REWOUND, AND THE FILES RESTORED TO THE ORIGINAL STR AT LEISURE. THE COMMAND STRING *DEV:_STR:FILESPECS/IS PERFORMS THE SAVE ONLY. LATER, A *DEV:_STR:/IR RESTORES IT FROM THE DEV TO THE STR (I KNOW THE COMMAND STRING IS BACKWARD, SORRY PIP USERS...). /I WITH NO OPTIONS IMPLIES BOTH, EXCEPT IN EXEC MODE OPERATION, IN WHICH CASE ONLY A /IS IS DONE. THE RESTORE MUST BE DONE UNDER THE CONTROL OF THE TIMESHARING MONITOR. > REPEAT LOGIC,< /I OPTIONS: R - RESTORE ONLY S - SAVE ONLY D - SAVE DELETED FILES ONLY (IGNORE BLOCKS MARKED IN SAT) E - SAVE EXISTING FILES ONLY (IGNORE BLOCKS FREE FROM SAT) A - SAME AS /IDE, SAVE ALL FILES, CHECK ALL BLOCKS. 2 - READ EVERY BLOCK EVEN IF NOT FIRST IN A CLUSTER (ALLOWS RECOVERY FROM 2ND RIBS) T - TIME OPTIONS. ASKS BEFORE AND AFTER. ONLY FINDS FILES BETWEEN GIVEN DATES AND TIMES O - OVERWRITTEN DATA ALLOWED (IF THE FILE HAS BEEN PARTIALLY OVERWRITTEN, NORMALLY, RIPOFF WILL DISCONTINUE THE RESTORE OF THAT FILE WHERE THO OVERWRITTEN DATA BEGINS. THERE IS NO (EASY) WAY TO TELL WHERE THE OVERWRITTEN DATA ENDS HOWEVER. IT IS POSSIBLE, FOR INSTANCE, TO HAVE A LARGE FILE (THAT WAS DELETED), AND HAVE A SMALL 1 BLOCK FILE OVERWRITE ONE LOUSY CLUSTER RIGHT IN THE MIDDLE. RESULTS: YOU GET ONLY HALF YOUR FILE BACK, BECAUSE RIPOFF MUST ASSUME THE ENTIRE REST OF THE FILE IS OVERWRITTEN (POSSIBLY). HOWEVER, WITH THE O OPTION, RIPOFF WILL RESTORE THE ENTIRE FILE, THAT IS ALL THOSE BLOCKS WHICH USED TO BE IN THE FILE. OF COURSE, SOME OF THESE BLOCKS WILL CONTAIN SOMEONE ELSES DATA. THIS IS OF COURSE, A SECURITY VIOLATION, AND SHOULD BE USED WITH CARE. HOWEVER, IN AN EMERGENCY SITUATION, IT IS WORTH HAVING AROUND. IT SHOULD NOT BE USED UNTIL A /I HAS BEEN TRYED WITHOUT IT AND COME UP WITH ONLY A PARTIAL RESTORE. F - FAILSAFE. RIB SEARCH LOGIC NOT USED. SIMPLY READS FILES FROM DISK, WRITES TO AUX, AND BACK FOR RESTORE. D,E,A AND 2 OPTIONS ILLEGAL WITH F. S AND R CANNOT BOTH BE USED AT THE SAME TIME. X - ADDED TO RESTORE OPTION OR PRINT OPTION, XLISTS OUTPUT OF FILE NAMES AND SIZES. ONLY UFD'S RESTORED ARE PRINTED. P - PRINT ONLY. READS TAPE AND PRODUCES DIRECTORY. > SWT.I: TXNN SW, ;IF NO SWITCH OPTIONS, TXO SW, ;ASSUME ALL OPTIONS. TXNE SW, TXNN SW,CH.F ;/IF CANT CO-EXIST WITH ABOVE SKIPA PJRST ERR011 ;TELL HIM HE IS MISTAKEN. TXNE SW,CH.R ;HE WANT A RESTORE? TXZ SW,CH.P ;YES. WE PRINT ANYWAY, SO KEEP ZERO. PUSHJ P,NXTSTR ;GET A STR INIT'ED JRST RIPDON JRST .-2 TXNN SW,CH.S ;WANT TO SAVE? JRST SWT.IR ;NO. JUST A RESTORE NOW. PUSHJ P,AUXINI ;MAKE SURE OUTPUT DEVICE IS THERE JRST ERR003 ;ELSE ALL IS LOST WHEN ITS TOO LATE. PUSHJ P,AUXENT ;ENTER SCRATCH FILE JRST ERR004 ;JUST TO MAKE SURE... SETZM LHEAD ;THE LIST HEADERS SETZM LHEAD+1 MOV .JBFF,.SVFF ;TO REDUCE CORE LATER TXNN SW,CH.T ;TIME OPTION?? JRST SW.I30 ;NO. SKIP THIS MOVEI M,[ASCIZ/ After:/] PUSHJ P,MSGTTY ;ASK QUESTION OUTPUT CMD, ;REALLY ASK IT! PUSHJ P,GTDATE ;LET HIM ANSWER IT MOVEM T3,AFTER ;AND STORE HIS ANSWER.. MOVEI M,[ASCIZ/ Before:/] PUSHJ P,MSGTTY OUTPUT CMD, PUSHJ P,GTDATE ;LET HIM ANSWER SECOND QUESTION MOVEM T3,BEFORE ;AND STORE TLNE T3,-1 ;DID HE GIVE ZERO DATE? JRST SW.I30 ;NO. AOK MSTIME T1, ;YES. HE WANTS HERE AND NOW DATE T2, PUSHJ P,.CNVDT ;GET T3=NOW HRR T3,BEFORE ;T3=NOW DATE ,, HIS TIME TRNN T3,-1 ;DID HE GIVE ZERO TIME TOO??? AOBJP T3,.+1 ;YES. FIX T3 = TOMORROW, 1 MS. PAST MIDNIGHT MOVEM T3,BEFORE ;STORE. SW.I30: TXNE SW,CH.F ;FAILSAFE? JRST FAILSA ;YES. GO DO IT NOW. SETOB T,SATFLG ;IF HE SAYS NOTHING, ASSUME /ID TXNE SW,CH.E ;SAVE ONLY EXISTING FILES HRRZM T,SATFLG ;YES. SATFLG .GT. 0, LOOK ONLY IN SATS. TXNE SW,CH.D ;SAVE ONLY DELETED FILES? SETOM SATFLG ;YES. SATFLG .LT. 0, LOOK ONLY OUT OF SAT TXNE SW,CH.A ;SAVE ALL? SETZM SATFLG ;YES. SKIPE SATFLG ;IF ALL, DONT NEED TO READ SATS PUSHJ P,RDSAT ;READ THEM SETZM SATFLG ;CANT, SO DONT MOVN T4,STRBPC ; Get negative blocks/cluster TXNE CH,CH.2 ; Unless second RIB recovery MOVNI T4,1 ; In which case use -1 MOVEM T4,SETBLK ; This is starting block HLRZ U,UNIDDB ;ON LOGICAL UNIT ZERO. SWT.I1: MOVEI P1,RIBCOD ;LOOK AT WORD 176 OF BLOCK MOVEI P2,CODRIB ;TO SEE IF IT HAS A 777777 IN IT MOVE T4,STRBPC ;READ ONLY ONE BLOCK/CLUSTER TXNE CH,CH.2 ;UNLESS HE SAYS OTHERWIZE. MOVEI T4,1 PUSHJ P,SEARCH ;GO LOOK FOR IT JRST SWT.I2 ;ALL DONE! MOVE T1,SETBLK TXO F,F.RIB PUSHJ P,RIBCHK ;SEE IF ITS REALLY A RIB JRST SWT.I1 ;NOT SO IGNORE IT ;GOT A RIB. SEE IF ITS ONE OF OURS.. PUSHJ P,CHKMAT ;SEE IF WE MATCH. JRST SWT.I1 ;NO. FORGET THIS FILE THEN. JRST CHKMA1 ;SKIP OVER WHAT USED TO BE INLINE CODE CHKMAT: TXNE F,S.PROJ ;CHECKING PROJECTS? JRST .+5 ;NO. * HLLZ T,BUF+RIBPPN HLLZ T4,USRPTH+.PTPPN ; CAME T,T4 ;MATCH? POPJ P, ;NO. FORGET FILE TXNE F,S.PROG ;CHECKING PROGRAMMER NUMBERS? JRST .+5 ;NOPE. * HRRZ T,BUF+RIBPPN HRRZ T4,USRPTH+.PTPPN ; CAIE T,(T4) ;MATCH? POPJ P, ;NOPE. MOVE T,BUF+RIBNAM TXNN F,S.NAM ;CHECKING NAMES? CAMN T,USRNAM ;YES. MATCH? SKIPA ;YES. GOT IT. POPJ P, ;NO. FORGET HLLZ T1,BUF+RIBEXT HLLZS USREXT TXNN F,S.EXT ;CHECKING EXTENSIONS? CAMN T1,USREXT ;YES. MATCH? JRST CPOPJ1 ;YEP! POPJ P, ;NO. NO MATCH AFTER ALL. CHKMA1: ;OK. I GOT A GOOD RIB HERE. LETS PUT HIM IN THE TABLES. MOVE T2,BUF+RIBSTS ;LOOK AT FILE STATUS TXNE T2,RIPNFS ;NO BACKUP BIT? JRST SWT.I1 ;YES. IGNORE IT. (CRASH.SAV,SAT.SYS, ETC) MOVE T2,BUF+RIBPPN CAMN T2,MFDPPN JRST SWT.I1 ;CANT SAVE MFDPPN! MOVEI P1,LHEAD PUSHJ P,FILDAT ;GET FILES CREATION DATE,,TIME IN T3 TXNN SW,CH.T ;TIME OPTION? JRST SWT.I4 ;NO. CONTINUE. CAML T3,AFTER ;BEFORE AFTER?? CAML T3,BEFORE ;AFTER BEFORE? JRST SWT.I1 ;YES TO EITHER. FORGET THIS FILE SWT.I4: HLRZ P1,(P1) ;P1=NEXT UFD BLOCK JUMPE P1,SWT.I3 ;HIT END. MUST BE A NEW UFD CAME T2,1(P1) ;SEEN HIM BEFORE? JRST SWT.I4 ;NO. KEEP LOOKING ;HERE IF WE FOUND HIS UFD, NOW SEE IF THE FILE ALREADY ;BEEN SEEN TOO. P1=ADR OF PPN BLOCK. MOVE P2,P1 ;REMEMBER PPN BLOCK IN P2 SWT.I5: HRRZ P1,(P1) ;P1:=ADR NEXT FILE BLOCK JUMPE P1,SWT.I6 ;MUST BE A NEW FILE NAME CAME T,1(P1) ;NAMES MATCH? JRST SWT.I5 ;KEEP LOOKING. HLLZ T4,(P1) CAME T1,T4 ;EXTENSIONS MATCH? JRST SWT.I5 ;KEEP LOOKING. ;HERE WHEN FILE OCCURED PREVIOUSLY CAMG T3,2(P1) ;CREATED LATER THAN FIRST ONE? JRST SWT.I1 ;NO. FORGET FILE COMPLETELY SWT.I9: ;THIS IS A LATER COPY OF THE FILE. MOVEM T3,2(P1) ;STORE NEW DATE,,TIME WORD MOVE T,SETBLK ;AND NEW RIB ADDRESS WORD MOVE T1,HOMLUN(U) DPB T1,[POINT 4,T,3] MOVEM T,3(P1) JRST SWT.I1 ;AND GO BACK FOR MORE RIBS NOW. ;HERE IF A NEW UFD FOUND. CREATE HIM AN ENTRY SWT.I3: MOVEI T,2 ;WE WILL INSERT HIS PPN BLOCK PUSHJ P,CORGRB ;INTO THE VERY BEGINNING OF THE LIST ;SINCE THAT IS THE EASIEST WAY... HLRZ T1,LHEAD ;T1=INITIAL PTR TO FIRST PPN HRLZM T1,(T) ;POINT US THERE INSTEAD HRLM T,LHEAD ;POINT INITIAL PTR TO US INSTEAD MOVEM T2,1(T) ;REMEMBER PPN IN CORE MOVE P2,T ;REMEMBER PPN ADDRESS IN P2 PUSHJ P,FILDAT ;GET UNIVERSAL DATE,,TIME INTO T3 ;AND FALL INTO .I6 TO CREAT FILE BLOCK ENTRY ;HERE WHEN NEW FILE NAME OCCURS. CREATE AN ENTRY FOR HIM. SWT.I6: MOVEI T,4 PUSHJ P,CORGRB HRRZ T1,(P2) ;T1=1ST FILE POINTED TO BY PPN HRRM T1,(T) ;POINT ME THERE INSTEAD HRRM T,(P2) ;POINT PPN TO ME INSTEAD MOVE P1,T ;SET P1=PTR TO FILE BLOCK TOO. MOV BUF+RIBNAM,1(P1) ;PUT IN MY NAME HLLZ T1,BUF+RIBEXT HLLM T1,0(P1) ;AND MY EXTENSION JRST SWT.I9 ;CONTINUE OVER THERE. ;HERE WHEN ALL FILES FOUND. NOW WRITE THEM TO SCRATCH AREA. SWT.I2: TXO F,F.IO ;WE WILL BE WRITING ON SCRATCH. PUSHJ P,AUXALC ;NOW ALLOCATE AUX BUFFERS. MOVEI P1,LHEAD SW.I0: HLRZ P1,(P1) ;MOVE UP TO NEXT PPN JUMPE P1,SW.I4 ;UNTIL DONE HRRZ P2,(P1) ;P2=ADR OF FIRST FILE BLOCK SW.I3: JUMPE P2,SW.I0 ;IF NO MORE FILES, TRY NEXT PPN MOVE T,1(P2) ;FILE NAME HLLZ T1,0(P2) ;EXTENSION LDB T2,[POINT 4,3(P2),3] ;LOGICAL UNIT # OF RIB IMUL T2,STRBPU ;T2=BLOCK NUMBER OF FIRST BLOCK ON UNIT LDB T3,[POINT 32,3(P2),35] ADD T2,T3 ;AND BLOCK ON UNIT TO IT, AND YOU GET MOVNS T2 ;-BLOCK IN STR OF FIRST RIB MOVE T3,1(P1) ;T3=PPN MOVEI P4,DSK PUSH P,P1 PUSH P,P2 PUSHJ P,LOOKP ;LOOKUP FILE FILE NOW. JRST SW.I1 ;WHAT????? MOVE P1,IOW MOVEM P1,XIOWD+DSK PUSHJ P,AUXOUT ;WRITE IT TO SCRATCH JFCL ;HMM. JFCL ;CANT HAPPEN EITHER! POP P,P2 POP P,P1 SW.I9: PUSHJ P,DMPIN ;READ A BLOCK OF THE FILE MOVE T,DSK+IOSTS TXNE T,IO.EOF ;EOF?? JRST SW.I2 ;YES. DONE TXO F,F.RIB ;NO NAME CHECK PUSHJ P,RIBCK0 ;READING A RIB? JRST SW.I14 ;NO. AOK ;YES. FILE HAS BEEN OVERWRITTEN. TXNE SW,CH.O ;OVERWRITING ALLOWED? JRST SW.I9 ;YES. CONTINUE READING FILE, IGNORE THIS RIB JRST SW.I2 ;NO. FILE IS DONE NOW. SW.I14: PUSH P,P1 MOVE P1,IOW PUSHJ P,AUXOUT ;NO. WRITE BLOCK TO SCRATCH JFCL JFCL POP P,P1 JRST SW.I9 SW.I2: HRRZ P2,(P2) ;DONE. GET NEXT FILE NAME JRST SW.I3 ;AND CONTINUE ;HERE ON LOOKUP FAILURE. (WHICH IS REALLY IMPOSSIBLE, SINCE WE ;ALREADY VERIFIED RIB..) SW.I1: POP P,P2 POP P,P1 HRRZ P2,(P2) ;GET NEXT FILE NAME JRST SW.I3 ;SIMPLY IGNORE THE FILE. ;HERE TO DO SIMPLE SAVES. NO LOGIC REQUIRED. JUST READ ;ALREAD EXISTING FILES AND PIP THEM TO AUX. FAILSA: TXNE SW,CH.R ;IF SAYS R, TXNN SW,CH.S ;THAN CANT SAY S SKIPA JRST ERR011 ;/IFSR. ILLEGAL TXNE SW,CH.R ;SAY RESTORE? JRST SWT.IR ;YES. DO IT THEN. TXO F,F.IO PUSHJ P,AUXALC ;GET SOME BUFFERS FAILS0: PUSHJ P,NXTPPN JRST SW.I4 ;DONE WHEN MFD DONE. MOVE T2,USRPTH+.PTPPN ; CAMN T2,MFDPPN JRST FAILS0 ;CANT SAVE MFD. FAILS1: PUSHJ P,NXTFIL ;GET NEXT FILE IN UFD JRST FAILS0 PUSHJ P,USRLOK ;GET ITS RIB JRST FAILS1 MOVE T2,BUF+RIBSTS TXNE T2,RIPNFS JRST FAILS1 ;DONT SAVE CRASH.SAV, ETC TXNN SW,CH.T ;WANT TIME OPTION? JRST FAILS2 ;NO. FORGET CHECK PUSHJ P,FILDAT ;YES. GET FILES CREATION DATE CAML T3,AFTER ;BEFORE AFTER? CAML T3,BEFORE ;AFTER BEFORE? JRST FAILS1 ;YES TO EITHER. IGNORE THIS FILE FAILS2: MOVE P1,IOW MOVEM P1,XIOWD+DSK MOVEI P4,DSK PUSHJ P,AUXOUT ;WRITE SOME, JFCL JFCL PUSHJ P,DMPIN ;THEN READ SOME. MOVE T,DSK+IOSTS TXNN T,IO.EOF ;UNTIL EOF ON DISK JRST FAILS2 JRST FAILS1 ;IN WHICH CASE, GET NEXT FILE. ;HERE WHEN SAVE COMPLETED. NOW RESTORE IF POSSIBLE SW.I4: PUSHJ P,AUXEOF ;WRITE EOF PUSHJ P,AUXRLS ;RELEASE DEVICE PUSHJ P,ZCORE ;REDUCE CORE BACK TO MINIMUM SWT.IR: TXNN SW,CH.R!CH.P ;WANT TO READ TAPE AGAIN NOW? JRST RIPDON ;NO. FORGET IT. PUSHJ P,AUXINI ;INITIALIZE SCRATCH AGAIN JRST ERR003 PUSHJ P,AUXLUK ;LOOKUP FILE JUST WRITTEN JRST ERR007 TXZ F,F.IO ;WE WILL BE READING ONLY MOV .JBFF,.SVFF ;SAVE TO REDUCE LATER. PUSHJ P,AUXALC ;NEED TO REALLOCATE BUFFERS. TXNE SW,CH.P ;PRINTING ONLY? JRST SW.IR1 ;YES. DONT BOTHER DISKS MOVEI T,14 ;AND SET UP OUR OWN STR TOO. MOVE T1,USRSTR ;I AM DOING THIS INSTEAD OF CALLING MOVSI T2,WH.STR ;INIDSK (WHICH INITS MODE 17) SO THAT OPEN STR,T ;OUTPUT CANN BE BUFFERED. I BELIEVE JRST NOSTR ;THAT FASTER /IR OPERATION IS MORE MOVE T,.JBREL ;IMPORTANT THAN EXEC MODE COMPATIBILITY OUTBUF STR,20 ;SET UP BUFFERS FOR THE OUTPUT CAME T,.JBREL ;INCREASE A K? PUSHJ P,PNTCOR ;YES. TELL HIM SO. SW.IR1: TXZ F,F.FAIL!F.RIP ;AOK SO FAR. TXNE SW,CH.P TXO F,F.FAIL ;JUST IN CASE.. SETOM PASS SW.I5: MOVE P1,IOW PUSHJ P,AUXIN ;READ A BLOCK FROM SCRATCH JRST .-2 ;JUST BETTER NOT HAPPEN! JRST SW.I10 ;EOF. ALL DONE!!!!! TXO F,F.RIB PUSHJ P,RIBCK0 ;RIB? JRST SW.I6 ;NO. STILL READING DATA FILE SW.I13: TXZN F,F.RIP ;WAS A RESTORE IN PROGRESS? JRST SW.I11 ;NO. TXNN SW,CH.P CLOSE STR, ;YES. CLEAN UP ENDS OF LAST FILE TXNE SW,CH.X JRST SW.I12+1 TTYON PUSHJ P,TAB MOVE N,UBLKCT ;TELL HIM HOW MANY BLOCKS WE FOUND PUSHJ P,DECPRT MOVE N,UBLKCT ;AND ORIGINAL LENGTH CAMN N,SETBLK ;IF DIFFERENT. JRST SW.I12 MOVEI M,[ASCIZ/ Original had:/] PUSHJ P,MSGTTY MOVE N,SETBLK PUSHJ P,DECPRT SW.I12: PUSHJ P,CRLF TXNN F,S.PROG!S.PROJ!S.NAM!S.EXT ;IF NO STARS, THEN WE ARE JRST RIPDN1 ;AFTER JUST ONE FILE! ;NOW WE HAVE FINISHED OFF THE LAST FILE. START PROCESSING THE ;NEXT ONE ON THE TAPE. SW.I11: SKIPN BUF+RIBNAM ;DO WE HAVE A NEXT ONE ON TAPE? JRST RIPDN1 ;NO. EOF (SEE SW.I10) PUSHJ P,CHKMAT ;YES. ONE OF OUR BOYS? JRST NORESTORE ;NO. SKIP HIM. MOV BUF+RIBNAM,USRNAM HLLZ T,BUF+RIBEXT HLLZM T,USREXT MOVE T,BUF+RIBPPN ;GET HIS PPN AOSE PASS ;IF NOT FIRST FILE, CAME T,USRPTH+.PTPPN ; SAME AS LAST ONE? TXOA F,F.TMP ;NO. OK TXZ F,F.TMP ;YES. SUPRESS UFDPNT MOVEM T,USRPTH+.PTPPN ; TTYON TXO F,F.NOTB ; Use dot instead of tab TXNN SW,CH.X PUSHJ P,FILPNT ;TELL HIM NEW FILE NAME TXZN F,F.TMP ;DID UFD CHANGE? JRST .+4 ;NO. DONT TELL HIM AGAIN. PUSHJ P,UFDPNT ;YES. TELL HIM NEW UFD TXNE SW,CH.X ;SUPPRESSING FILES? PUSHJ P,CRLF ;YES. BETTER ADD A CR NOW. OUTPUT CMD, ;MAKE SURE IT GETS OUT, MAY BE AWHILE TILL DONE. ;HERE TO DO ENTER AT LAST. SW.I8: ;Following instruction removed to prevent the zeroing of the ;3 high-order bits of the creation date. (U. of Texas) ;[75] HLLZS BUF+RIBEXT ;SET UP UUOBLK MOVI RIBSTS,BUF+RIBFIR SETZM UBLKCT ;ZERO FILE SIZE. TXO F,F.RIP ;RESTORE ABOUT TO START NOW. MOVE T,BUF+RIBSIZ ;SIZE ACCORDING TO RIB ADDI T,BLKSIZ-1 IDIVI T,BLKSIZ MOVEM T,SETBLK ;UBLKCT COUNTS OUTPUTS, SETBLK HOPEFULLY. TXNE SW,CH.P JRST NORESTORE ;SKIP ENTER IF JUST PRINTING ENTER STR,BUF ;USE STANDARD MONITOR ENTER SKIPA JRST SW.I5 ;AND CONTINUE READING FILE ;HERE ON ENTER FAILURE. DO SOMETHING FAST! HRRZ T,BUF+EXLERC CAIN T,ERPOA% ;PARTIAL ALLOCATION ONLY? JRST SW.I5 ;YES. THAT'S OK. (FILE NOT CONTIGOUS) CAIE T,ERIPP% ;GUY GOT NO UFD YET? JRST SW.I7 ;WORSE. OY VEY! MOVE T,[BUF,,DSK+DATBUF] BLT T,DSK+DATBUF+RIBSTS ;SAVE UUOBLK SOMEPLACE SAFE PUSHJ P,MAKUF1 ;GO MAKE HIM A UFD QUICK TXOA F,F.FAIL TXZ F,F.FAIL MOVS T,[BUF,,DSK+DATBUF] BLT T,BUF+RIBSTS ;RESTORE OUR FILE BLOCK TXNN F,F.FAIL ;UFD THERE NOW? JRST SW.I8 ;YES. TRY ENTER AGAIN.. ;HERE ON HORRIBLE ERROR. CANT CREATE A FILE SW.I7: TXZ F,F.RIP TXNN SW,CH.X JRST SW.I7A TXO F,F.NOTB ; Use dot instead of tab PUSHJ P,FILPNT ;NEED TO TELL HIM NAME IF DIDNT BEFORE PUSHJ P,UFDPNT SW.I7A: MOVEI M,[ASCIZ/ ENTER failure code:/] PUSHJ P,MSGTTY HRRZ N,BUF+EXLERC PUSHJ P,OCTPRT PUSHJ P,CRLF SETSTS STR,14 NORESTORE: TXO F,F.FAIL JRST SW.I5 ;CONTINE READING FILE FROM AUX, ;BUT F.FAIL TELLS NOT TO WRITE IT ;(JUST PASS IT) ;HERE TO ACTUALLY RESTORE THE DAMN DATA SW.I6: AOS UBLKCT ;COUNT BLOCK LENGTH ON TAPE TXNE F,F.FAIL ;RESTORING? JRST SW.I5 ;NO. JUST IGNORE THIS BLOCK MOVE T,[-200,,BUF] SW.I21: SOSLE WH.STR+2 JRST SW.I20 OUT STR, JRST SW.I20 MOVEI M,[ASCIZ/ OUTPUT error/] PUSHJ P,MSGTTY SETSTS STR,.IODMP JRST SW.I5 SW.I20: MOVE CH,(T) ;GET A WORD IDPB CH,WH.STR+1 ;PUT INTO BUFFER AOBJN T,SW.I21 ;AND LOOP FOR 200 WORDS JRST SW.I5 ;AND CONTINUE FOR REST OF FILE. ;HERE WHEN HIT EOF ON AUX DEVICE, CLOSE LAST FILE AND QUIT SW.I10: SETZM BUF+RIBNAM ;SIMPLE FLAG TO SW.I11 CODE JRST SW.I13 ;GO CLEAN UP ENDS UU(WH.STR,3) ;DISK OUTPUT BUFFER HEADER FOR RESTORE CODE. SUBTTL /L -- Lock job in core ; ; /L options include: ; ; /L - Lock job in core ; /LU - Unlock job SWT.L: TXNE SW,CH.U ; Want to unlock or lock? JRST UNLOCK ; Unlock SKIPL %LOCK ; Lock. Are we already? JRST SWT.L1 ; No. OK JSP M,MSGDON ; Dont need to lock twice.. ASCIZ/%Job already locked/ SWT.L1: PUSHJ P,LOCKUUO ; Go lock the job JRST NOLOCK ; Cant... SETOM %LOCK JSP M,MSGDON ASCIZ/Job locked/ UNLOCK: AOSG %LOCK ; Locked already? JRST UNLOK1 JSP M,MSGDON ASCIZ/%Job not locked/ UNLOK1: MOVE N,ONEONE UNLOK. N, ; Unlock us please.. JRST NOLOCK ; Hmm... JSP M,MSGDON ASCIZ/Job unlocked/ NOLOCK: TTYON MOVE T,[3,,LOKERR] PUSHJ P,ERRPNT ; Print the error code PUSHJ P,CRLF JRST RIPDON LOKERR: ERRMAC ?LOCK UUO gone! , ?Job not privilleged ERRMAC ?Another job would not be able to run, ?Can't guarantee CORMAX SUBTTL /P -- Print according to format SWT.P: TXNN SW, JRST DSKLST ; DSKLST if no print options JRST DATLST ; Otherwise, DATLST to list blocks SUBTTL /R -- Read verify disk blocks ; Simply reads all given blocks. ; Any which might be hardware unreadable are diagnosed by BLKRED... ; Defaults are BARG1=0, BARG2=Largest in STR, BARG3=1 block at a time SWT.R: SKIPN BARG3 ; Zero increment? AOS BARG3 ; Yes. Make it one SWT.R0: PUSHJ P,NXTSTR JRST RIPDON JFCL MOV BARG1,BUF ; BUF=block to start on. MOV BARG2,BUF+1 ; BUF+1=Last block to try MOVE T,STRHGH ; T=Highest log. block in STR CAMG T,BARG2 ; Which should be more than he wants JRST SWT.R2 ; Not even RIPOFF can read non-ex blocks! SOS T SKIPN BARG2 ; Ask for zero max? MOVEM T,BUF+1 ; Yes. Assume maximum then MOV BARG3,BUF+2 ; BUF+2=block to increment by MOVE T1,BUF SWT.R1: CAMLE T1,BUF+1 ; Done yet? JRST SWT.R0 ; Yes. Get more disks MOVEM T1,BUF ; Remember new block number MOVE T,[IOWD BLKSIZ,DSK+DATBUF] ; No. T=IOWD MOVEI P4,DSK PUSHJ P,STRRED ; Go get it.. JFCL ; Thats one... MOVE T1,BUF ADD T1,BUF+2 ; Try next block JRST SWT.R1 ; Here on illegal maximum arg SWT.R2: MOVEI M,[ASCIZ/?Only /] PUSHJ P,MSGTTY MOVE N,T PUSHJ P,OCTPRT ; MOVEI M,[ASCIZ/ Blocks on STR/] PJRST MSGDON SUBTTL /S -- Manipulate SAT blocks/STRUUO functions ; Options: ; /SL Lock up STR (.FSLOK, then .FSREM) ; /SR Read SATs (DSKSAT) ; /SW Write them back ; /SF Free cluster in SAT ; /SM Mark cluster in SAT ; /SP Print sat as now in core ; /ST Type a cluster, i.e., tell free or marked SWT.S: SWT.S0: PUSHJ P,NXTSTR ; Get next structure JRST RIPDON ; All done JFCL ; Don't care about MFD TXNN SW, JRST SWT.S1 PUSHJ P,SATINC ; SATs must be already be in core JRST ERR008 SWT.S1: TXNN SW,CH.L ; Want to lock the STR? JRST SWT.S2 ; No. Continue on ; Here to lock out a STR. PUSHJ P,LOKSTR ; Do .FSLOK JRST SWT.S0 MOVEI T,^D10 CAMGE T,BARG1 ; If more then 10 seconds, tell him to PUSHJ P,MSG001 ; 'Wait plz...' SKIPN T,BARG1 ; Sleep BARG1 seconds MOVEI T,^D60 ; Default is 1 min SLEEP T, ; Wait a while PUSHJ P,REMSTR ; Do .FSREM now. JRST SWT.S0 MOVEI T,[MOVEI T,.DCSTN ; For all units in STR, set pack-not DPB T,[POINTR UNIDES(U),DC.STS] ; mounted status POPJ P, ] PUSHJ P,DOALLU ; Do for all units JRST SWT.S0 ; Done. Try other STR's if so wanted. SWT.S2: TXNN SW, JRST SWT.S5 ; Here to read or write SATs TXNN SW,CH.W ; Skip if writing SATs JRST SWT.S3 PUSHJ P,WTSAT ; Go write SATs then JRST ERR009 JRST SWT.S0 ; Got em. SWT.S3: TXNN SW,CH.R JRST SWT.S4 PUSHJ P,RDSAT ; Read SATs... JRST ERR009 JRST SWT.S0 SWT.S4: SETZM TOTSAT ; Here to print SATs. MOVEI T,[PUSHJ P,PNTSAT ; Print each SAT ADDM N,TOTSAT ; Accumulate STR totals POPJ P, ; For each unit ] PUSHJ P,DOALLU PUSHJ P,CRLF MOVE N,TOTSAT PUSHJ P,DECPRT ; Print STR total blocks free MOVEI M,BLKMSG PUSHJ P,MSG MOVEI M,TOTMSG PUSHJ P,MSG JRST SWT.S0 ; Here if /SM or /SF or /ST SWT.S5: MOVE P1,BARG1 SWT.S6: CAML P1,STRHGH JRST SWT.S0 MOVE T,P1 IDIV T,STRBPU ; T=unit,T1=block on unit MOVE U,STRUNI(T) ; U=UDB MOVE T,DSKSAT(U) ; T=Addr of SAT table, T1=block within table IDIV T1,STRBPC ; T1=Cluster within table TXNE SW,CH.T ; Want me just to type this? JRST SWT.S7 ; Yes. Go type MOVEI T2,MRKZRO ; No. Set up to mark or free TXNE SW,CH.M ; Decide to MRKONE or MRKZRO. MOVEI T2,MRKONE PUSHJ P,(T2) ; Do one. JFCL SWT.S8: ADD P1,STRBPC ; On to next cluster CAMGE P1,BARG2 ; Within bounds? JRST SWT.S6 ; Yes. Do it too. JRST SWT.S0 ; No. Done ; Here to type out a bit SWT.S7: MOVEI P2,[ASCIZ/ marked/] PUSHJ P,TSTONE ; See if marked MOVEI P2,[ASCIZ/ free/] MOVEI M,[ASCIZ/Cluster /] PUSHJ P,MSGTTY MOVE N,P1 IDIV N,STRBPC ; PUSHJ P,OCTPRT ; MOVE M,P2 PUSHJ P,MSGTTY PUSHJ P,CRLF JRST SWT.S8 ; Continue for more clusters if he wants SUBTTL /U -- Create new UFD/SFD ; Make a new UFD/SFD. Gives error messages if it already ; exists. Will not create over already existing one SWT.U: TTYON SWT.U1: PUSHJ P,NXTSTR ; Get next STR JRST RIPDON ; until done JRST SWT.U1 ; Gotta have a MFD PUSHJ P,RLSDSK PUSHJ P,INIDSK ; Get us a disk SETOM CURLVL ; Take running start at nesting SWT.U2: AOS CURLVL ; Bump nesting level by one PUSHJ P,SETUFD ; Setup for this one JRST SWT.U3 ; None found so print error LOOKUP STR,BUF ; Go! SKIPA P1,BUF+EXLERC ; Not there! Wonderful. JRST SWT.U2 ; There, so loop for next in path HRRZS P1 JUMPE P1,SWT.U4 ; Better be 0=file not found SKIPA ; SWT.U3: MOVEI P1,ERAEF% ; Simulate error if already there MOVE M,USRSTR ; Get current structure PUSHJ P,PR6BIT ; and print it too PUSHJ P,COLON ; PUSHJ P,UFDPNT ; and current path HRRZ N,P1 ; SETZ T, ; PUSHJ P,ERRPNT ; Print error message PUSHJ P,CRLF ; Tidy up JRST SWT.U1 ; Give up on this str ; Here when OK to make UFD/SFD SWT.U4: PUSHJ P,MAKUFD ; Go make a UFD JRST SWT.U1 ; Error or done MOVEI M,[ASCIZ/Created /] ; Tell of success PUSHJ P,MSG ; print it MOVE M,USRSTR ; Get current str PUSHJ P,PR6BIT ; and print it PUSHJ P,COLON ; PUSHJ P,UFDPNT ; and current path PUSHJ P,CRLF ; AOS CURLVL ; Bump SFD nesting level JRST SWT.U4 ; and try next level SUBTTL /V - Verify files and rebuild SATs ; File RIBs are checked, all blocks of the file are ;read (If A option), second RIBs are found and verified, and file is ;checksummed and SAT bits are checked (DSKRAT) ;and compared against disk SATs to find multiply used, free and lost clusters SWT.V: SETCM T,F TXNN T,STNDRD ; Were all files specified? TXOA F,F.TRB ; Yes, tell routines to look for trouble TXZ F,F.TRB ; No, forget it SETOM PASS ; Count passes PUSHJ P,NXTSTR ; Get a STR JRST RIPDON ; If all done JRST .-3 ; Must have a MFD MOVE T,USRSTR ; Get specified str TXNE F,F.TRB ; Looking for trouble? CAME T,LSTDEV ; and STR same as LST device? SKIPA ; No to one PUSHJ P,ASK005 ; Yes, question his judgement TXNN SW,CH.F ; Going to fix SATs? JRST SWT.VA ; Nope MOVE T,TTYTYP ; Get original device type CAIE T,$DVSTR ; and other than STR specified? JRST ERR015 ; Gotta have STR to fix SATs PUSHJ P,STRMNT ; Is this STR mounted? JRST ERR016 ; Yes, can't do this SWT.VA: MOV .JBFF,.SVFF ; Save current field length TXZE F,F.TRB ; If looking for trouble, PUSHJ P,RDSAT ; read SATs. TXZA F,F.TRB ; Can't do it, so don't look for trouble TXO F,F.TRB ; Got 'em, reset the flag MOVEI T,[ PUSHJ P,SATADD ; Allocate space for trouble SAT on MOVEM T,TRBSAT(U) ; all units POPJ P, ] PUSHJ P,DOALLU ; Do above code on all units TXNN SW,CH.A ; Read all blocks? TXZA F,F.RALL ; No, make sure it doesn't happen TXO F,F.RALL ; Yes, tell input routines SWT.V1: TTYOFF ; Turn off TTY output MOV .JBFF,TEMP3 ; Remember core before OURSAT allocated TXNE SW,CH.Q ; If quick wanted, TXO F,F.QUICK ; Let it be so. PUSHJ P,BLDSAT ; Now go build a SAT from file ; information, noticing troubles in TRBSAT PUSHJ P,SETBAT ;SET BITS FOR BLOCKS POINTED TO BY BAT AOSE PASS JRST SWT.V4 ; Only make two passes PUSH P,F ; Save flags for F.TRB TXZN F,F.TRB ; Did we read SATs above?? PUSHJ P,RDSAT ; No. Read them now. SKIPA P4,[$PRLST] ; Yes. We looked for trbl before MOVEI P4,$PRFRE ; No. Dont look for it now! PUSHJ P,PRALL ; Print lost, free and mult clusters POP P,T ; Unless only did a few files (F.TRB not set) AND T,[F.TRB] ; In which case only free and mult. TDO F,T ; Reset state of F.TRB in F.. PUSHJ P,FORM ; Form feed to output listing MOVEI M,[ASCIZ/ End of pass 1 on /] PUSHJ P,MSGTTY ; Tell of event MOVE M,USRSTR ; Get STR we've been doing PUSHJ P,PR6BIT ; Tell him which STR. TXNE F,F.MULT ; Any multiply used clusters? JRST SWT.V2 ; Yes. MOVEI M,[ASCIZ/. No need for pass 2./] ; No. PUSHJ P,MSG JRST SWT.V4 SWT.V2: MOVEI M,[ASCIZ/. Beginning Pass 2./] PUSHJ P,OPER ; Make sure he wants it JRST SWT.V4 MOV TEMP3,.JBFF ; Restore .JBFF to deallocate OURSAT ; So that BLDSAT will start all over again. PUSHJ P,REWSTR ; Rewind the str JRST DIE003 ; Succeeded once! JRST DIE003 JRST SWT.V1 ; and go do it again ; Now, if /VA, read rest of str too... SWT.V4: TXNN SW,CH.A ; Well? JRST SWT.V5 ; Nope. TXNN F,F.TRB ; Must have read in SATs to do this.. JRST SWT.V0 ; Forget it SETOB P1,P2 ; Test BUF(P1)=C(P2) SETZM BUFHED ; BUF(P1)=zero, P2=-1, match is doubtfull.. SETOM SATFLG ; Read only if not in DSKSAT SETOM SETBLK ; Begin at block 0 MOVEI T,[ MOV OURSAT(U),DSKSAT(U) ; Move SAT pointers POPJ P, ]; So that OURSAT becomes DSKSAT PUSHJ P,DOALLU HLRZ U,UNIDDB MOVEI T4,1 ; Increment by 1 block PUSHJ P,SEARCH ; Search for a block that cannot be found SKIPA ; Done... JRST .-2 ; If found, ignore it ; Now rewrite sats back out if /VF SWT.V5: TXNN SW,CH.F ; Want it? JRST SWT.V0 ; No. Done TXNN F,F.TRB ; Do *.*[*,*]?? JRST ERR010 ; No. Cant do it. TXNE CH,CH.A ; Go through /VA above? JRST SWT.V6 ; Yes. Forget this MOVEI T,[ MOV OURSAT(U),DSKSAT(U) ; No, Make DSKSAT=OURSAT POPJ P, ] PUSHJ P,DOALLU SWT.V6: MOVEI M,[ASCIZ/ Prepared to rewrite SATS/] PUSHJ P,OPER ; Make sure he wants it JRST SWT.V0 TXZ F,F.TRB!F.OURS ; Dont look at bits again! PUSHJ P,WTSAT ; Rewrite SATs then..... JRST ERR009 ; Ohboy! ; Here when all done, deallocate core and continue SWT.V0: MOV .SVFF,.JBFF ; Restore .JBFF JRST SWT.V SUBTTL /W -- Do word searches REPEAT LOGIC, < /W options include: /WM - Set search mask to specified value /WW - Set search word to specified value /WT - Type current values of search mask and word /WS - Start word search for specified values > SWT.W: TXNN SW,CH.T ; Typing values? JRST SWT.W1 ; No TTYON ; Enable TTY output PUSHJ P,SWWPRT ; Type the values PJRST RIPDON ; and finish up SWT.W1: TXNN SW,CH.M ; Setting mask register? JRST SWT.W2 ; No MOV BARG1,WMASK ; Set new value PJRST RIPDON ; and finish up SWT.W2: TXNN SW,CH.W ; Setting search word? JRST SWT.W3 ; No MOVE T,BARG1 ; Assume it looked like a block number SKIPN GOTWRD ; Are we correct? MOVE T,USRNAM ; No, get something that looks like this MOVEM T,WWORD ; Set new value PJRST RIPDON ; and finish up ; Here to do the search for the specified word. Note that one ; may search files or relative blocks. SWT.W3: TXNN SW,CH.S ; Better be start of search JRST ERR001 ; No, bad option PUSH P,BARG1 ; Save value for later SETOM PASS ; Count number of matches SWT.W4: PUSHJ P,NXTSTR ; Get next STR JRST [POP P,BARG1 ; Restore BARG1 JRST RIPDON] ; and finish up JFCL ; Don't care about MFD SWT.W5: SKIPE GOTWRD ; Skip if no block arg JRST SWT.W8 ; Go process blocks PUSHJ P,NXTPPN ; Get next PPN JRST SWT.W4 ; If none left SWT.W6: PUSHJ P,NXTFIL ; Get next file JRST SWT.W5 ; If none left PUSHJ P,USRLOK ; Lookup the file JRST SWT.W6 ; Not there MOV IOW,XIOWD+DSK ; Setup IOWD to read into BUF SWT.W7: MOVEI P4,DSK ; Setup core block pointer PUSHJ P,DMPIN ; Get the next block of the file MOVX T,IO.EOF ; Get EOF flag TDNE T,IOSTS+DSK ; Hit EOF? JRST SWT.W6 ; Yes, try next file PUSHJ P,WRDMAT ; Search this block and print matches JRST SWT.W7 ; and loop for rest of file ; ; Here to do block searches SWT.W8: MOVEI P4,DSK ; Setup core block pointer MOVE T1,BARG1 ; Get next block to read MOVE T,IOW ; Get IOWD to use PUSHJ P,STRRED ; Read the block JFCL ; Oh well, do the search anyway PUSHJ P,WRDMAT ; Search this block AOS T,BARG1 ; Bump the block count CAMG T,BARG2 ; Done enough? JRST SWT.W8 ; No, loop for more JRST SWT.W4 ; Try next structure SUBTTL /X -- Perform cleanup and exit ; Options are: ; /XQ - Run QUEUE automatically after closing files ; MSGXIT: PUSHJ P,MSGTTY ; Here to print msg and exit SWT.X: PUSHJ P,KILL ; Close listing files TXNN SW,CH.Q ; Want to run QUEUE too?? EXIT ; No. Forget everthing.. MOVSI T,DSYS ; Yes. Go get it! MOVE T1,[SIXBIT .QUEUE.] SETZB T2,T4 OUTSTR [ASCIZ/ .R QUEUE /] JRST RUNCOM ; and go run it!! ; Here to CLOSE and RELEAS all listing files and devices KILL: OUTPUT CMD, TXNE F,F.TTY2 JRST .+3 KILL1: OUTPUT LST, CLOSE LST, PUSHJ P,RLSDSK RELEAS LST, POPJ P, SUBTTL ^C INTERCEPT CODE ; No one seems to be able to remember to exit with a /X command ; after writing the listing to a file. A ^C is used instead and ; if no CLOSE is done, the listing is lost. To prevent this, ; the page contains the ^C intercept code. If the user types ; a ^C when the listing is being written to a file, ask him ; if he wants to close the file. Enter at CZEXIT to process ; a ^Z instead. CCEXIT: PUSH P,INTBLK+.EROPC ; Save interupt PC SETZM INTBLK+.EROPC ; Reenable intercept CZEXIT: ; [075] Control-Z entry point TXNE F,F.TTY2 ; Output going to TTY? JRST CCEXT2 ; Yes CLRBFO ; Clear output buffer PUSH P,M ; Save M and TEMP PUSH P,TEMP ; (Used by OPER) MOVEI M,[ASCIZ/ Close listing file before exiting?/] PUSHJ P,OPER ; Ask user JRST CCEXT1 ; He says no POP P,TEMP ; Restore TEMP and POP P,M ; M PUSHJ P,KILL1 ; Clean up EXIT ; and quit CCEXT1: POP P,TEMP ; Restore TEMP and POP P,M ; M CCEXT2: MONRT. ; Exit quietly POPJ P, ; Return if he says CONTINUE SUBTTL SYSINI - RIPOFF once-only initialization code ; Subroutine to determine system disk configuration and build ; a UNIDDB for all units. ; Called only once at program startup time SYSINI: MOVEI U,UNIDDB ; Start at beginning SETOM CTYPE ; Current controller type SYSIN1: AOS T,CTYPE ; 0,1,2,3,4,5=FHA,FHB,DPA,DPB,RPA,RPB CAILE T,TYPMAX ; Done all possible types? JRST SYSIN3 ; Yes. Continue on SETOM CUNIT ; No. Try all units here SYSIN2: AOS T,CUNIT ; 0-7 units CAILE T,MAXUNI ; Skip if still in range JRST SYSIN1 ; Not, so try another controller MOVSS T HRR T,CTYPE ; T=XWD unit,, controller type PUSHJ P,INIPHY ; INIT this unit. Return with T1=Unit name JRST SYSIN2 ; Cant so forget it MOVEM T1,USRSTR ; Remember its physical name PUSH P,T ; Save DSKCHR bits MOVEI T,UNIDDL ; Length of one UDB PUSHJ P,CORGRB ; Grab the core MOVEM T,(U) ; Save initial ptr in last UDB for link MOVE U,T ; U=adr of this UDB now. POP P,UNIDES(U) ; Store DSKCHR bits in UDB ; Now determine what brand of disk pack we have here.. MOV <[Z STR,T]>,XCHAN(U) ; Tell BLKRED how to look MOV USRSTR,DRIVE(U) ; And where to look MOV BIGNUM,BLKUNI(U) ; Don't let IO.BKT get me MOVEI P4,DSK ; Give it a channel data block MOVE T,CTYPE ; Get controller type HRRZ T4,KONADR(T) ; Get addr of AOBJN pointer MOVE T4,(T4) ; Get pointer itself SYSI8A: MOVEM T4,DSKPTR ; Save ptr to table MOVE T1,1(T4) ; Get blocks / unit SOS T1 ; Try to read next to last block MOVE T,IOW TXO F,F.DERR ; Suppress error msg if any. PUSHJ P,BLKRED ; .. JFCL MOVE T,DSK+IOSTS ; Get I/O status TXNN T,IO.ERR ; Errors? JRST SYSI8B ; No. Got it MOVE T4,DSKPTR ; Yes. Try smaller pack ADD T4,[2,,2] ; Update pointer AOBJN T4,SYSI8A ; and loop. ; If none of the blocks read, must have a bad pack... Forget it SKIPA M,[[ASCIZ/Can't establish unit type for unit /]] SYSI8C: MOVEI M,[ASCIZ/Unit type inconsistency for unit /] PUSHJ P,MSGTTY MOVE M,USRSTR PUSHJ P,PR6BIT MOVEI M,[ASCIZ/, setting status = down /] PUSHJ P,MSGTTY JRST SYSIN2 ; and loop for more units ; Found unit type. Set up parameters for it SYSI8B: MOVE T,1(T4) MOVEM T,BLKUNI(U) ; Blocks/unit HRRZ T,0(T4) MOVEM T,BLKCYL(U) ; Blocks/cylinder HLRZ T,0(T4) MOVEM T,BLKTRC(U) ; Blocks/track JRST SYSIN9 ; Skip tables ; Following are the tables of disk parameters used by RIPOFF in the ; initialization code. ; ; To add a new controller type, add it's SIXBIT name to the table ; KONSIX and in the same relative position in KONADR, add the ; DSKCHR controller type code and the pointer to the appropriate ; AOBJN pointer to the unit tables. To add a new type of disk ; drive, select the controller type on which it is to be used and ; determine the correct disk table from the pointer. In that table, ; add the necessary attributes for the drive. Note that the ; blocks/unit parameters in each table must be in strictly decreasing ; order. DEFINE DSKTAB(A,B,C,D) < XWD A,B EXP C EXP D > ; BLKS/TRACK , BLKS/CYL , BLKS/UNIT , DSKCHR unit type ; Table for drives on RP controller %RH10: DSKTAB ^D20, ^D380, ^D307800, .DCUR6 ;RP06 DSKTAB ^D20, ^D380, ^D154280, .DCUR4 ;RP04 %RHLEN==.-%RH10 ; Table for FS drives on an RH10 %RHS10: DSKTAB ^D32, ^D2048, ^D2048, .DCUS4 ; [076] RS04 %RSLEN==.-%RHS10 ; [076] ; Table for drives on DP controller %RP10: DSKTAB ^D10, ^D200, ^D80000, .DCUD3 ;RP03 DSKTAB ^D10, ^D200, ^D40000, .DCUD2 ;RP02 %RPLEN==.-%RP10 ; Table for drives on FH controller %RC10: DSKTAB ^D20, ^D4000, ^D4000, .DCUFD ;RD-10 DSKTAB ^D30, ^D2700, ^D2700, .DCUFM ;RM10-B %RCLEN==.-%RC10 ; Below is a table of controller types to look for. The nth ; element of KONSIX contains the SIXBIT name of the controller ; and is indexed by CTYPE. The corresponding entry in KONADR ; contains the controller DSKCHR bits and the pointer to the ; AOBJN word for the units associated with the controller. ; ; Table of controller names KONSIX: SIXBIT . FHA. SIXBIT . FHB. SIXBIT . DPA. SIXBIT . DPB. SIXBIT . DPC. SIXBIT . FSA. ; [076] In KONSIX table SIXBIT . FSB. ; [076] SIXBIT . RPA. SIXBIT . RPB. SIXBIT . RPC. SIXBIT . RPD. ;[APC] TYPMAX==.-KONSIX-1 ; ; Table of corresponding pointers to AOBJN words KONADR: .DCCFH,,FHPTR .DCCFH,,FHPTR .DCCDP,,DPPTR .DCCDP,,DPPTR .DCCDP,,DPPTR .DCCFS,,FSPTR ; [076] In KONADR before 1st RP entry .DCCFS,,FSPTR ; [076] .DCCRP,,RPPTR .DCCRP,,RPPTR .DCCRP,,RPPTR .DCCRP,,RPPTR ;[APC] ; ; AOBJN pointers to associated unit types FHPTR: -%RCLEN ,, %RC10 DPPTR: -%RPLEN ,, %RP10 RPPTR: -%RHLEN ,, %RH10 FSPTR: -%RSLEN ,, %RHS10 ; [076] ; End of disk tables ; Here when we know unit, set up home stuff SYSIN9: SETZM (U) ; Incase this is the last UDB. HRLZ T,CTYPE HRR T,CUNIT MOVEM T,DEVKON(U) ; Type,, unit HLRZS T ; Get type in RH HLRZ T,KONADR(T) ; Get DSKCHR controller type bits LDB T1,[POINTR UNIDES(U),DC.CNT] ; Get type from monitor CAME T,T1 ; Better be the same JRST SYSI8C ; Otherwise, something's wrong LDB T,[POINTR UNIDES(U),DC.UNT] ; Get monitor DSKCHR unit code CAME T,2(T4) ; Better be the same as we found JRST SYSI8C ; Otherwise error PUSHJ P,HOMCHK ; Attempt to read it JRST SYSIN2 ; Quit if no home blocks SKIPN BUF+HOMHID ; or if no ID. JRST SYSIN2 HRRZI T,1(U) ; Adr. of UDB+1 HRLI T,BUF+1 ; Adr of disk block+1 BLT T,HOMEND-1(U) ; Zap block into UDB MOVE T,BLKUNI(U) ; Blocks/unit IDIV T,HOMBPC(U) ; T=full clusters/unit SUBI T,1 ; T=(clusters/unit)-1 IDIV T,HOMSPU(U) ; T=(clusters/SAT)-1 MOVEM T,UNICPS(U) ; Store it AOS UNICPS(U) ; clusters/SAT=(((clus/unit)-1)/(SAT/unit))+1 IDIVI T,^D36 ; words/SAT=(((clus/SAT)-1)/(clus/word))+1 ADDI T,1 MOVEM T,UNIWPS(U) ; Words/SAT block HRRZI T,P1 HRRM T,HOMCLP(U) ; Make all byte ptrs point to P1 HRRM T,HOMCNP(U) HRRM T,HOMCKP(U) JRST SYSIN2 ; Loop for all units ; Here to set up STRTAB REPEAT LOGIC,< STRTAB: BLOCK 1 ; Initial ptr to following table SIXBIT .STR1. ; Table somewhere in core Z,,ADR. Unit 0 UDB Z,,ADR. Unit 1 UDB Z,,ADR. Unit N UDB SIXBIT .STR2. ; Note that all SIXBITs are negative Z,,ADR. Unit 0 UDB ; While addresses are positive Etc.. Z,,Z ; Ends the list > SYSIN3: MOVEI T,*+1 ; PUSHJ P,CORGRB ; Get max core for the JOB MOVEM T,STRTAB ; Initial ptr MOVEI U,UNIDDB ; Adr. first UDB SYSIN4: HRRZ U,(U) ; Adr. next UDB JUMPE U,SYSIN7 ; Until done. SKIPN T,HOMSNM(U) ; See what STR this unit's on JRST SYSIN4 ; None. Forget it SKIPL T1,HOMLUN(U) ; If negative unit, CAILE T1,MAXUNI ; or out of normal range, JRST SYSIN4 ; Probably just random bulsht. Forget it SKIPA P1,STRTAB ; Begin at STRTAB SYSIN5: ADDI P1,MAXUNI+2 ; Look at next entry SKIPN T1,(P1) ; Is it zero? JRST SYSIN6 ; Yes. Hit end without match. ; This is a new STR. Add it to list CAME T,T1 ; No. Is this the same as ; STR this unit's on? JRST SYSIN5 ; No. Keep looking SKIPA ; Yes. STR already in table. Just ; UDB entry for this unit. SYSIN6: MOVEM T,(P1) ; Put new STR in table MOVEI T,1(P1) ; Adr. of entry for unit 0 ADD T,HOMLUN(U) ; Adr for unit N MOVEM U,(T) ; Put UDB adr there JRST SYSIN4 ; and continue for all units ; Here to compress STRTAB. Skip zero words SYSIN7: MOVNI T,* ; HRL T,STRTAB MOVSS T ; IOWD to table for AOBJN MOVSI P1,(POINT 36,0,35) ; P1=36 bit byte pointer HRRI P1,-1(T) ; to str table SKIPE T1,(T) ; Is it zero? IDPB T1,P1 ; No. Put it back in table AOBJN T,.-2 ; Loop for whole table SETZ T, IDPB T,P1 ; End it with a zero ADDI P1,1 HRRZM P1,.JBFF ; Conserve core not used now POPJ P, ; That is it. System is initialized ; Subroutine to INIT a device on channel STR ; Call T= XWD unit ,, controller type ; Ret+0 No such unit ; Ret+1 with T1=Device name. ; T = monitor DSKCHR bits ; M,T,T2 destroyed INIPHY: PUSHJ P,PHYNAM ; Construct physical name MOVEI T,.IODMP ; Dump mode MOVE T1,M ; Name SETZ T2, OPEN STR,T POPJ P, MOVE T,[1,,M] DSKCHR T, ; Do DSKCHR to see what monitor says SETZ T, ; No bits JSP M,TTYOUT ; Turn on TTY now TXNE T,DC.OFL ; Is it off-line? PUSHJ P,INI001 ; Yup. So monitor tells me. TXNE T,DC.HWP ; Write protected? PUSHJ P,INI002 ; Uh-huh LDB T2,[POINTR T,DC.STS] ; Get status bits (DC.STS field) JUMPE T2,CPOPJ1 ; Zero is OK CAIN T2,.DCSTD PUSHJ P,INI003 ; The unit is down CAIN T2,.DCSTN PUSHJ P,INI004 ; No pack mounted CAIN T2,1 PUSHJ P,INI005 ; Reserved for future! JRST CPOPJ1 ; Thats all folks.. ; Here to type error (warning actually) messages. ; Type unit name, message, and ask to ignore monitor status. INI001: JSP M,INI000 ASCIZ/ is off-line/ INI002: JSP M,INI000 ASCIZ/ is write protected/ INI003: JSP M,INI000 ASCIZ/ is down/ INI004: JSP M,INI000 ASCIZ/ has no pack mounted/ INI005: JSP M,INI000 ASCIZ/ has broken the time barrier/ INI000: PUSH P,M ; Save message address MOVE M,ST$OPT ; Get the startup option CAIE M,$OPLON ; Was it LONG? JRST [POP P,(P) ; Get rid of message address JRST INI047 ]; and go simulate NO answer PUSH P,T ; Save DSKCHR bits across calls MOVEI M,[ASCIZ/ Unit /] PUSHJ P,MSGTTY MOVE M,T1 ; Get unit name PUSHJ P,PR6BIT POP P,T ; Restore T POP P,M ; Restore message address PUSHJ P,MSG ; and print it MOVEI M,[ASCIZ/ Type YES to ignore error, NO to consider pack down/] PUSHJ P,OPER ; Ask for confirmation SKIPA POPJ P, ; He says ignore. Return. INI047: POP P,(P) ; He says no. POP return to INIPHY POPJ P, ; and make like INIT error, no such unit. ; Subroutine to construct physical device controller name. ; Call T=XWD Unit ,, Controller type ; Ret M=Name PHYNAM: HLRZ M,T ; Unit number ADDI M,'0' ; Make it SIXBIT LSH M,^D12 HRL M,KONSIX(T) ; Put in controller name POPJ P, ; and exit SUBTTL RIPUUO - File service routines for RIPOFF ; Subroutine to find and initialize (INIT) next structure ; Ret+0 No more structures ; Ret+1 Next STR fixed up, but no MFD on STR ; Ret+2 Next STR fixed up, and MFD OK on channel MFD NXTSTR: JSP M,SAVE3 ; Save a few AC's SETOM CURLVL ; Set nesting level to -1 (MFD) TXZ F,F.MFD!F.1UNI ; No MFD yet and not in pass 2 MOVE T,TTYTYP ; Get DEVTYP of original name CAIE T,$DVCNT CAIN T,$DVCON JRST @NXTTAB(T) JUMPN T,.+2 JRST @NXTTAB(T) ; If 3,4 or 0 , process now ; Here if 1,2,5 or 6 - can only be called once AOSE STRFLG ; Been here before? JRST NXTDON ; Yes. Clear bits and popj CAIE T,$DVSTR ; No. Type 1? TXO F,F.1UNI ; No. Type 2,5,6 all have only one unit JRST @NXTTAB(T) ; and dispatch on DEVTYP NXTTAB: NXTST0 NXTST1 NXTST2 NXTST3 NXTST4 NXTST5 NXTST6 NXTDON: SETOM STRFLG HRRZS UNIDDB TXZ F,F.1UNI POPJ P, ; Here if type 0= DSK (Generic) ; Each call will return another structure in system linked in UDBs NXTST0: SKIPE T,USRSTR ; Get last STR name PUSHJ P,FNDSTR ; Find it in STRTAB MOVE P1,STRTAB ; Not found so start with first one. SKIPLE U,(P1) ; Find the next name in table AOJA P1,.-1 JUMPE U,NXTDON ; Unless were at the end now MOVE T,(P1) MOVEM T,USRSTR ; OK. Got next one ; Here with U=Unit 0 UDB address, P1=Adr of STR name in STRTAB NXTSTA: MOVEI U,UNIDDB ; Start with UNIDDB NXTSTB: SKIPG T,1(P1) ; Look through table JRST NXTSTC ; Until next STR name HRLM T,(U) ; Moving UDB addresses to UDB links MOVE U,T AOJA P1,NXTSTB NXTSTC: HRRZS (U) ; End it all with a zero in LH link JRST LNKDON ; and we're done. ; Here if type 1 = specific structure name ; Return only once linking that STR NXTST1: MOVE T,USRSTR ; Get its name PUSHJ P,FNDSTR ; Find it in table JRST DIE004 ; Gotta be there SOJA P1,NXTSTA ; and go link this STR now and return ; Here if type 2 = specific unit in structure (DSKB3) ; or type 5 = specific unit on a controller (DPA3) ; or type 6 = specific home ID (PRV001) ; ; All return exactly one unit each call NXTST2: NXTST5: NXTST6: MOVE U,TTYDDB ; UDB found in scanner HRLM U,UNIDDB ; It is only link JRST NXTSTC ; Go add a zero eol and continue ; Here if type 3 = controller type (DP) ; or type 4 = specific controller (DPB) ; Return one unit on each call NXTST3: NXTST4: MOVE T,TTYSTR PUSHJ P,MSKUNI ; Make mask in T1 HLRZ U,UNIDDB ; Get adr. of last unit found SKIPN U ; None? HRRZ U,UNIDDB ; Well then use first unit NXTSTD: MOVE U,(U) ; Go to next UDB in system JUMPE U,NXTDON ; Unless no more MOVE T2,DRIVE(U) AND T2,T1 ; Get units name to a few chars CAME T,T2 ; Match? JRST NXTSTD ; No. Keep trying HRLM U,UNIDDB ; Yes. got one MOV DRIVE(U),USRSTR ; Remember its name JRST NXTSTC ; Add zero ptr and go home ; Here when structure units linked ; Now initialize STRUNI table, INIT units with monitor LNKDON: SETZM HIGHU ; Highest unit in STR SETZM STRBPU ; Highest blocks/unit in STR SETZM STRSIZ ; Total number of blocks in the STR SETZM STRUNI ; Table of units in STR MOVE T,[STRUNI,,STRUNI+1] BLT T,STRUNI+MAXUNI ; Clear out a few things first MOVEI U,UNIDDB MOVEI P1,FFCHAN ; P1=Channel to INIT unit on NXTSTE: HLRZ U,(U) ; Get next unit in STR JUMPE U,NXTSTF ; Until done MOVE T,HOMLUN(U) TXNE F,F.1UNI MOVEI T,0 ; If not a STR, make it look like unit 0 CAILE T,MAXUNI JRST DIE004 CAMLE T,HIGHU MOVEM T,HIGHU ; Calculate highest unit MOVEM U,STRUNI(T) ; and make table OK MOVE T,BLKUNI(U) CAMLE T,STRBPU MOVEM T,STRBPU ; Caculate highest blks/unit in STR ADDM T,STRSIZ ; By counting total blocks in STR MOVEM T,CURPOS(U) ; Impossible position, force positioning. MOVEI T,T DPB P1,[POINT 4,T,12] MOVEM T,XCHAN(U) TLO T,(RELEASE) XCT T ; RELEASE CHAN,T MOVEI T,.IODMP ; Dump mode INIT MOVE T1,DRIVE(U) ; Physical name SETZ T2, MOVE T3,XCHAN(U) TLO T3,(OPEN) XCT T3 ; OPEN CHAN,T JRST DIE006 AOJA P1,NXTSTE ; Loop for all units in STR ; Here when str all set up, release all channels not used ; and see if we can find the MFD NXTSTF: MOVSI T,(RELEASE) ; Set to release DPB P1,[POINT 4,T,12]; All still unused channels XCT T CAIGE P1,17 AOJA P1,NXTSTF ; Loop for 17 channels HLRZ U,UNIDDB ; Get a unit UDB ptr back HRLZI N,HOMGRP(U) ; Save a few structure parameters HRRI N,STRGRP ; For each structure. BLT N,STRBPC ; From UDB to resident core MOVE T,HIGHU ; Highest unit ADDI T,1 ; +1 for unit 0 IMUL T,STRBPU ; Times blks per unit MOVEM T,STRHGH ; =highest blk on STR MOVE T,BARGFL ; Get block arg flags MOVE T1,STRBPC ; Blocks/cluster TRNE T,1 ; Block arg 1 # ? IMULM T1,BARG1 ; Yes. Fix it TRNE T,2 ; BARG2? IMULM T1,BARG2 ; IBID. TRNE T,4 IMULM T1,BARG2 SETZM BARGFL ; and forget flags now REWSTR: HLRZ U,UNIDDB MOVE T,MFDPPN ; Get MFD now MOVSI T1,'UFD' MOVN T2,HOMMFD(U) MOVE T3,MFDPPN MOVEI P4,MFD AOS (P) ; Set for at least single skip return MOVE N,HOMUN1(U) ; Log unit where MFD starts TXNE F,F.1UNI ; Only one unit 'structure'? CAMN N,HOMLUN(U) ; Yes. Dont even try lookup if MFD not on this unit.. PUSHJ P,LOOKP ; Look for it PJRST NOMFD ; Not there. Give non-fatal msg and skip return TXO F,F.MFD ; Got it. Flag it. JRST CPOPJ1 ; and give double skip ret. ; Subroutine to find the next PPN or directory in accordance with ; the command specs. ; ; RIPOFF contains two different tree search algorithms. The combination ; of NXTPPN and NXTFIL perform a post-order tree traversal by processing ; the files in each SFD before processing the SFD itself. This is ; done by enabling NXTFIL to scan for SFD's itself and dropping down ; one level when it finds one that matches the command string. The ; combination of NXTDIR and NXTFIL perform a pre-order tree traversal ; by processing all files at a given level before trying to find any ; SFD's at a lower level. In general, the NXTDIR/NXTFIL algorithm ; is used where a nice format is desired (/P), it is impossible to ; do it the other way (/A), or where speed is not important. As ; a result, one will find, for example, that the /F, /W, and /V ; code use the NXTPPN/NXTFIL combination because they do not need ; the slower NXTDIR/NXTFIL combination. ; ; Both return CPOPJ if no more directories ; CPOPJ1 with the directory setup NXTDIR: TXZ F,F.NPP!F.SCAN ; Flag entry as NXTDIR, disable scanning SKIPGE T,CURLVL ; Skip if not first call for this STR JRST NXTPP1 ; On first call, do a NXTPPN MOVE P4,CORBLK(T) ; Point to core block for this level MOVE T,FNAME(P4) ; Setup for LOOKP by getting values MOVE T1,FEXT(P4) ; current values from core block MOVE T2,FCFP(P4) MOVEI T3,FPATH(P4) PUSHJ P,LOOKP ; LOOKUP directory, thus rewinding it JRST DIREOF ; Can't, fake EOF ; ; Here to reread the directory at the current level looking for ; lower level directories that match the command string ; NXTDI1: PUSHJ P,R.UFD ; Read next entry from directory JRST DIREOF ; If no more entries MOVE T,CH ; Save the filename PUSHJ P,R.UFD ; Read ext,,cfp JRST DIREOF ; If no more entries JUMPE T,NXTDI1 ; Ignore if empty HRRM CH,USRCFP ; Save the CFP HLRZS CH ; Isolate extension in RH CAIN CH,'SFD' ; This an SFD? PUSHJ P,CHKSFD ; Yes, check for command string match JRST NXTDI1 ; No to one, ignore it PUSHJ P,LOOKP ; LOOKUP the directory JRST DIREOF ; Can't, simulate EOF MOVE T,CURLVL ; Get level back SKIPN MATFLG(T) ; Can files be matched at this level? JRST NXTDI1 ; No, avoid futile calls to NXTFIL AOS (P) ; Bump return point POPJ P, ; and return with new directory ; ; Here when the current directory runs out ; DIREOF: SKIPN CURLVL ; Done all directories in this PPN? JRST NXTPP1 ; Yes, call NXTPPN again SOS P4,CURLVL ; Decrement level MOVE P4,CORBLK(P4) ; Point to next higher core block JRST NXTDI1 ; and continue with that one ; ; Enter here to get the next PPN as opposed to the next directory ; NXTPPN: TXO F,F.NPP!F.SCAN ; Flag NXTPPN entry and enable scanning NXTPP1: PUSHJ P,R.MFD ; Read one word of the MFD JRST MFDEOF ; If MFD done, try next STR's MFD MOVE T3,CH ; Save the word PUSHJ P,R.MFD ; Read next entry JRST MFDEOF JUMPE T3,NXTPP1 ; Even MFD's have zeroes HRRZM CH,UFDCFP ; Save CFP to the UFD HLRZS CH CAIE CH,'UFD' JRST NXTPP1 ; MFD's also have files other than UFD's. TXNE F,S.PROJ ; Looking for a particular project? JRST NXTPP2 ; No. This one's OK. Try the programmer # HLRZ T1,T3 ; Proj # from MFD HLRZ T2,USRPTH+.PTPPN ; Proj # from file specs CAME T2,T1 ; Do they match? JRST NXTPP1 ; No. Try another entry NXTPP2: TXNE F,S.PROG ; Looking for a particular programmer? JRST NXTPP3 ; No. Continue on HRRZ T1,T3 ; Yes. Compare MFD programmer # HRRZ T2,USRPTH+.PTPPN; to user programmer # CAME T2,T1 ; Do they match? JRST NXTPP1 ; No. Try, try again ; ; Here when we have a PPN that matches the command string. ; NXTPP3: MOVEM T3,USRPTH+.PTPPN; We have our number NXTPP4: MOVEI P4,UFD ; Point to correct core block MOV UFDCFP,FCFP(P4) ; Save CFP of this directory SETZB T1,CURLVL ; Setup for CHKPTH and indicate top level PUSHJ P,CHKPTH ; See if files are matchable in UFD MOVE T,USRPTH+.PTPPN ; get our number MOVSI T1,'UFD' MOVE T2,UFDCFP MOVE T3,MFDPPN PUSHJ P,LOOKP ; LOOKUP his UFD JRST NXTPP1 ; Ignore bad UFD's TXNN F,F.NPP ; Enter at NXTPPN SKIPE MATFLG+0 ; No, match files on this level? JRST CPOPJ1 ; Yes, return success JRST NXTDI1 ; Avoid futile calls to NXTFIL ; ; Here when the MFD runs out ; MFDEOF: TXZ F,F.MFD ; MFD no longer looked up POPJ P, ; Return ; Routine to return the next file from a given path in accordance ; with the command string. If F.SCAN is set, NXTFIL will process ; the files in an SFD found at the current level that matches the ; command string. ; ; Returns CPOPJ on EOF on current level if F.SCAN is not set, ; on EOF at top level if F.SCAN is set ; Returns CPOPJ1 if file found with USRNAM, USREXT, USRCFP, USRPTH, ; and P4 setup NXTFIL: PUSHJ P,R.UFD ; Read filename from current level JRST UFDEOF ; EOF on this level MOVE T,CH ; Save the filename PUSHJ P,R.UFD ; Get EXT,,CFP JRST UFDEOF ; EOF on this level JUMPE T,NXTFIL ; If entry is empty HRRZM CH,USRCFP ; Save CFP of file HLRZS CH ; Move extension to right half CAIN CH,'SFD' ; This an SFD? TXNN F,F.SCAN ; and scanning enabled? JRST NXTFI2 ; Nope, try it as a file PUSHJ P,CHKSFD ; SFD match command string? JRST NXTFI2 ; No, process as a file PUSHJ P,LOOKP ; Lookup this SFD JRST UFDEOF ; Can't, simulate EOF PJRST NXTFIL ; Go process files in SFD ; ; Here when we have a possible candidate at a given level. ; See if we match the filename and extension specified in ; the command string. ; NXTFI2: MOVE T1,CURLVL ; Get current level SKIPN MATFLG(T1) ; Files matchable on this level? JRST NXTFIL ; No, continue HRLZS CH ; Move ext back to left half TXNE F,S.NAM ; Need to match name? JRST NXTFI3 ; No CAME T,USRNAM ; The same? JRST NXTFIL ; No dice, go get next one NXTFI3: TXNE F,S.EXT ; Need to match extension? JRST NXTFI5 ; No CAME CH,USREXT ; Match? JRST NXTFIL ; Nope NXTFI5: MOVEM T,USRNAM ; Save name and MOVEM CH,USREXT ; extension AOS (P) ; Set for skip return POPJ P, ; and return ; ; Here when we reach an EOF on the current level. If scanning was ; enabled, back out one level and setup to process the SFD itself ; as a file. ; UFDEOF: TXNE F,F.SCAN ; Scanning enabled? SKIPN P4,CURLVL ; Yes, backed out all the way already? POPJ P, ; Yes, really an EOF MOVE P4,CORBLK(P4) ; Get current core block MOV FCFP(P4),USRCFP ; Get CFP for the SFD MOVE T,FNAME(P4) ; and the filename MOVEI CH,'SFD' ; to process the SFD as a file SOS P4,CURLVL ; Decrement level MOVE P4,CORBLK(P4) ; and point to new core block JRST NXTFI2 ; Go process SFD ; Routine to check for an SFD that matches the command string ; Call with T = SFD name ; Returns CPOPJ if no match ; CPOPJ1 if the SFD matches with ; T-T3 setup for LOOKP ; CURLVL incremented and P4 setup ; MATFLG setup for new level ; Path setup in TMPPTH CHKSFD: SKIPN %FTSFD ; System have SFD's? POPJ P, ; No, so can't match them MOVE T1,CURLVL ; Get current SFD level TXNN F,S.SFD ; All SFD's stars? SKIPE SFDFLG+1(T1) ; or just star at next level? JRST CHKSF1 ; Yes, this is a match MOVE T1,USRPTH+.PTPPN+1(T1) ; Get name at next level CAME T,T1 ; Match with this one? POPJ P, ; No, return ; ; Here if the SFD matches the command string. Drop down one level and ; setup to process the files in the new SFD. ; CHKSF1: AOS T1,CURLVL ; Bump current level PUSHJ P,CHKPTH ; Setup MATFLG appropriately MOVEM T,USRPTH+.PTPPN(T1) ; Save matching SFD name MOVE T2,[USRPTH,,TMPPTH] ; Get BLT pointer to move path BLT T2,TMPPTH+.PTPPN+1+SFDLVL+1-1 ; Move path to where we can diddle it SETZM TMPPTH+.PTPPN+1(T1) ; Insure zero terminator at correct place MOVE P4,CORBLK(T1) ; Point to new core block MOVSI T1,'SFD' ; Extension is SFD MOVE T2,USRCFP ; Get CFP of SFD MOVEM T2,FCFP(P4) ; Save in core block MOVEI T3,TMPPTH ; Point to path AOS (P) ; Set for skip return POPJ P, ; and return ; ; ; ; Routine to see if files can be matched at a given level of nesting ; Call with T1 = level to check ; Returns CPOPJ always with MATFLG(T1) set appropriately ; ; Preserves T1 CHKPTH: SETZM MATFLG(T1) ; Assume files cannot be matched TXNE F,S.SFD ; Stars on all levels? JRST CHKPT1 ; Yes, files are matchable CAME T1,CMDLVL ; Deepest level specified in command string? SKIPE SFDFLG+1(T1) ; or next level a star? CHKPT1: SETOM MATFLG(T1) ; Yes, files are matchable POPJ P, ; Return PNOMFD: PUSHJ P,NOMFD ; Tell of no MFD on this STR JRST RIPDON ; and continue NOMFD: MOVEI M,[ASCIZ/ No MFD on /] PUSHJ P,MSGTTY MOVE M,USRSTR PUSHJ P,PR6BIT TXZ F,F.MFD PUSHJ P,CRLF2 TTYOFF POPJ P, NOSTR: SKIPN USRSTR JRST NOSTR1 ; Didnt type any STR MOVEI M,[ASCIZ/ ?No such STR - /] PUSHJ P,MSGTTY MOVE M,USRSTR PUSHJ P,PR6BIT JRST SCAN NOSTR1: MOVEI M,[ASCIZ/?Must specify a STR/] MSGDON: PUSHJ P,MSGTTY PUSHJ P,CRLF2 JRST RIPDON ; Subroutine to find out what type of disk argument we have supplied ; in AC T. ; ; Return+0 always with T1=type code. ; ; Types are: $DVGEN==0 ; Generic disk (D,DS,DSK,ALL, or zero arg) $DVSTR==1 ; STR name (DSKA,DSKB) $DVLUN==2 ; Logical unit within a STR (DSKA3) $DVCNT==3 ; Controller type(DP,FH,MD) $DVCON==4 ; Controller (DPA,FHB) $DVPHD==5 ; Physical drive within controller (DPA3,FHA0) $DVPID==6 ; Pack ID (PRV006,LIB000) ; or T1=-1 if none of the above... ; ; U = Unit UDB address (unless type 0, U unspecified) ; ; ; Note that other types may be added. Program should not check for type ; 6 by CAIGE instruction. DEVTYP: JUMPE T,DEVTY0 ; Zero arg, return zero CAMN T,[SIXBIT/ALL/] ; Was it ALL:? JRST DEVTY0 ; Yes, return $DVGEN PUSHJ P,MSKUNI ; Make T1=mask for as many chars as typed MOVSI T2,'DSK' ; Look for generic AND T2,T1 ; Only as exact as he wants CAME T,T2 ; That it? JRST DEVTY3 ; No. got to look at UDB's.. DEVTY0: MOVEI T1,$DVGEN ; Yes. Return zero code POPJ P, ; and exit DEVTY3: MOVEI U,UNIDDB ; Look at UDBs DEVTY1: HRRZ U,(U) ; Get next UDB JUMPE U,DEVTY2 ; or zero if hit end CAME T,HOMSNM(U) ; Is it a STR? JRST DEVTY4 MOVEI T1,$DVSTR ; Yep. POPJ P, ; Return it DEVTY4: CAME T,HOMLOG(U) ; How about a log unit within STR? JRST DEVTY5 MOVEI T1,$DVLUN ; Yup POPJ P, CONT. DEVTY5: CAME T,HOMHID(U) ; Would you believe a pack ID? JRST DEVTY6 ; Nope. MOVEI T1,$DVPID ; Uh-huh POPJ P, DEVTY6: MOVE T2,DRIVE(U) ; Now look at physical names AND T2,T1 ; Mask it CAME T,T2 ; Match? JRST DEVTY1 ; No. No matches at all. Try next unit MOVE T1,DRIVE(U) ; Yes. Get back drive name CAME T,T1 ; Exact match? JRST DEVTY7 MOVEI T1,$DVPHD ; Yes. Physical drive name POPJ P, DEVTY7: TRZ T1,-1 ; Get rid of drive number CAME T,T1 ; Try again JRST DEVTY8 MOVEI T1,$DVCON ; Match. Controller POPJ P, DEVTY8: TLZ T,77 ; Get rid of controller type CAME T,T1 JRST DEVTY1 ; No match. Try another unit MOVEI T1,$DVCNT ; Made it! Two letter cont. type POPJ P, ; Here when done all units, and still no matches found DEVTY2: SETO T1, ; Give error AC=-1 POPJ P, ; Subroutine to find a name in STRTAB ; Call T=SIXBIT name ; Ret+0 Not found ; Ret+1 T unaltered ; P1=Adr of match + 1 ; U=(P1)= Adr of first unit UDB. ; FNDSTR: MOVE P1,STRTAB ; Start looking at STRTTAB FNDST1: SKIPLE U,(P1) ; Look at entry AOJA P1,.-1 ; Wait for negative or zero JUMPE U,CPOPJ ; If zero, hit end with no match CAME T,U ; Minus. Must be a STR name AOJA P1,FNDST1 ; But must be our name.. MOVE U,(P1) ; Adr unit 0 UDB AOJA P1,CPOPJ1 ; and quit ; Subroutine to execute a given subroutine ; for U=each unit of STR. ; Call T=Address of subroutine ; Subroutine may destroy T.. ; Must CPOPJ always, no skip returns please DOALLU: MOVEI U,UNIDDB ; Start at beginning HLRZ U,(U) ; and move up a unit JUMPE U,DOALL1 ; Until hit the end. PUSH P,T ; Save one valuable AC PUSHJ P,(T) ; Go do something POP P,T ; Restore AC JRST DOALLU+1 ; and loop for each unit DOALL1: HLRZ U,UNIDDB ; Set U=Unit 0 POPJ P, ; and return. ; Subroutine to determine if a structure is mounted ; Returns CPOPJ if it is, ; CPOPJ1 if it isn't STRMNT: PUSH P,U ; Save current U MOVEI U,UNIDDB ; Point at start of chain STRMN1: HLRZ U,(U) ; Move to next unit JUMPE U,UPOPJ1 ; Return not mounted at end LDB T,[POINTR UNIDES(U),DC.STS] ; Get status for this unit CAIE T,.DCSTN ; "Pack not mounted"? JRST UPOPJ ; No, either mounted or down JRST STRMN1 ; Loop for all units ; Subroutine to actually INIT a disk channel on channel STR. ; This is actually against RIPOFF philosophy, since ; we don't like to ask the monitor for UUO's when we can do them ourselfes. ; However, in some instances it pays to ask for help, such as DELFIL ; which tries monitor DELETE/RENAME first, then RIPOFF RENAME ; if that fails. Also /U code creates UFD's with monitor ENTERS. INIDSK: TXOE F,F.INI ; Already INITed? POPJ P, ; Yes. Forget it MOVEI T,.IODMP MOVE T1,USRSTR SETZ T2, OPEN STR,T JRST NOSTR POPJ P, ; Subroutine to release the STR channel INIT'ed by INIDSK RLSDSK: TXZ F,F.INI RELEAS STR, POPJ P, ; Subroutine to read and verify home blocks on a unit ; Call with U=UDB address ; Ret+0 Home block error. Appropriate message typed ; on console. ; Ret+1 Home block in BUF HOMCHK: JSP M,TTYOUT ; Turn on TTY I/O for this MOVEI T1,LHOM1 ; Log address of first home block MOVE T,IOW ; IOWD to buffer MOVEI P4,DSK ; Adr. for channel core block PUSHJ P,BLKRED ; Read 1st home block JRST HOM3 ; Read error MOVSI T,'HOM' CAME T,BUF+HOMNAM JRST HOM2 ; 1st is not SIXBIT 'HOM' MOVEI T,CODHOM CAME T,BUF+HOMCOD JRST HOM2 ; 1st does not have proper code MOVEI T,LHOM1 CAMN T,BUF+HOMSLF JRST CPOPJ1 ; Looks OK now.. JRST HOM2 ; Not OK. Try 2nd home block HOM3: SKIPA M,[[ASCIZ/ IOERR reading first HOME block /]] HOM2: MOVEI M,[ASCIZ .First HOME block consistency error on .] PUSHJ P,MSG MOVE M,DRIVE(U) PUSHJ P,PR6BIT ; Print unit here PUSHJ P,CRLF MOVEI T1,LHOM2 ; Try 2nd home block MOVE T,IOW PUSHJ P,BLKRED JRST HOM4 ; IOERR MOVSI T,'HOM' CAME T,BUF+HOMNAM JRST HOM5 ; 2nd fails too. MOVEI T,CODHOM CAME T,BUF+HOMCOD JRST HOM5 MOVEI T,LHOM2 CAME T,BUF+HOMSLF JRST HOM5 MOVEI M,[ASCIZ/Second HOME block is consistent. Error recovered/] AOS (P) ; Give OK return PJRST MSG ; Here if both home blocks in error. HOM4: MOVEI M,[ASCIZ/IOERR 2nd HOME block/] PJRST MSG HOM5: MOVEI M,[ASCIZ/Second HOME block consistency error./] PJRST MSGTTY ;Subroutine to read and verify BAT blocks on a unit ;Call with U=UDB address ;Ret+0 BAT block error. Appropriate message typed ; on console. ;Ret+1 BAT block in BUF BATCHK: MOVEI T1,LHOM1+1 ;Log address of first BAT block PUSHJ P,BAT9 CAIA JRST CPOPJ1 MOVEI M,[ASCIZ /First BAT block is bad on /] PUSHJ P,MSG MOVE M,DRIVE(U) PUSHJ P,PR6BIT ;Print unit here PUSHJ P,CRLF MOVEI T1,LHOM2+1 ;Try 2nd BAT block PUSHJ P,BAT9 JRST BAT4 MOVEI M,[ASCIZ /Second BAT block is consistent. Error recovered/] AOS (P) ;Give OK return PJRST MSG ;Here if both BAT blocks in error. BAT4: MOVEI M,[ASCIZ /Second BAT block is bad/] PJRST MSG ;HERE TO READ BAT BLOCK ;T1 PASSES BLOCK NUMBER OF WHICH BAT TO READ ;NOSKIP IF ERROR OR INCONSISTANT ;SKIP IF OK BAT9: TXZ F,F.CSUM+F.DERR ;JUST TO BE SURE SETZM NOIO MOVE T,IOW ;IOWD to buffer MOVEI P4,DSK ;Adr. for channel core block PUSHJ P,BLKRED ;Read BAT block POPJ P, ;Read error MOVS T1,BUF+BAFNAM ;Test consistency MOVE T2,BUF+BAFCOD CAIN T1,'BAT' CAIE T2,CODBAT POPJ P, JRST CPOPJ1 ;Looks OK ; Subroutine to verify a RIB block in BUF. ; Call T1=Log block in unit of RIB ; If F.RIB not set in LH(F), ; FNAME(P4)=File name ; FEXT(P4)=Extension ; FPPN(P4)=PPN ; If F.RIB is set, ; Check on file names not made, ; name need not be set up (P4) ; ; Ret+0 RIB error ; RIBCHK: MOVE T,T1 IDIV T,STRBPU CAME T1,BUF+RIBSLF ; Must agree. POPJ P, RIBCK0: MOVEI T,CODRIB CAME T,BUF+RIBCOD ; Code word in RIBCOD POPJ P, TXZE F,F.RIB ; Check file names?? JRST RIBCK2 ; No. Skip this MOVE T,FPPN(P4) CAME T,BUF+RIBPPN ; PPN's must match POPJ P, MOVE T,FNAME(P4) CAME T,BUF+RIBNAM ; along with file names POPJ P, HLLZ T,FEXT(P4) HLLZ T1,BUF+RIBEXT CAME T,T1 ; and file extensions. POPJ P, RIBCK2: HRRZ T,BUF+RIBFIR ; # of retrvl ptrs. Must be valid CAIG T,BLKSIZ-2 SKIPL BUF+RIBFIR ; and must also be negative POPJ P, JRST CPOPJ1 ; Yup. This looks like a real RIB! ; Subroutine to set up a search mask for a name. ; Call T=Name ; Return T unchanged, ; T1=mask MSKUNI: SKIPN T1,T ; Get name POPJ P, ; Not a name - Return mask=0 MOVSI T2,770000 ; Set up one char mask UNIMS1: TDON T1,T2 ; This char zero? JRST UNIMS2 ; Yes. Have mask LSH T2,-6 ; No. Shift & try next char JUMPN T2,UNIMS1 UNIMS2: TDZ T1,T2 ; Zero the last byte POPJ P, ; and return mask in T1 SUBTTL LOCK UUO routines ; Subroutine to do LOCK UUO. ; Will try 8 times every 2 seconds... ; Ret+0 Failed in 16 seconds ; Ret+1 Made it... both segments locked LOCKUUO: MOVEI N1,10 ; 8 tries LOCKU1: MOVE N,ONEONE LOCK N, ; Try to lock SKIPA JRST CPOPJ1 ; Got it. Return SOJLE N1,CPOPJ ; Too many failures, forget it HRRZS N ; Get the error code TRNN N,777776 ; If it is 0 or 1, POPJ P, ; Then forget it MOVEI N,2 SLEEP N, ; Sleep a while JRST LOCKU1 ; and try again ; Subroutines to do STRUUO functions ; Call PUSHJ P,LOKSTR ; To lock USRSTR ; PUSHJ P,REMSTR ; To remove it... zap. ; ; Ret+0 UUO error. Can't do it. Error msg typed. ; Ret+1 Got it. LOKSTR: SKIPA T,[.FSLOK] ; Set for lock REMSTR: MOVEI T,.FSREM ; Set for remove UUOSTR: MOVEM T,UUOFNC UUOST0: MOVE T,UUOFNC MOVE T1,USRSTR MOVEI N,T STRUUO N, ; Attempt UUO SKIPA JRST CPOPJ1 ; Got it! CAIE N,FSUNC% ; Cant complete it? JRST .+4 MOVEI T,1 ; No, sleep a second SLEEP T, JRST UUOST0 ; and try again JSP M,TTYOUT ; Other error, report failure MOVEI M,[ASCIZ/ STRUUO error on /] PUSHJ P,MSG MOVE M,USRSTR PUSHJ P,PR6BIT MOVEI M,[ASCIZ/ function /] PUSHJ P,MSG MOVE N,UUOFNC PUSHJ P,OCTPRT SETO T, PUSHJ P,ERRPNT PJRST CRLF U(UUOFNC) SUBTTL UUO level routines ; Subroutine to do a 'LOOKUP' or 'ENTER' UUO ; Call ; T=File name ; T1=File extension ; T2= +CFP or -log. block in STR ; T3=PPN or path pointer ; P4=Channel block address ; ; Ret+0 Error code in T1 and BUF+EXLERC ; Ret+1 File found, RIB left in BUF ; ENTR: TLOA P4,1 ; Flag entry point LOOKP: TLZ P4,1 MOVEM T,FNAME(P4) ; Store name, MOVEM T1,FEXT(P4) ; Extension, MOVEM T2,RIBLBN(P4) ; RIB address TLNN T3,-1 ; PPN or path pointer? JRST LOOKP2 ; Path pointer MOVEM T3,TMPPTH+.PTPPN; Save the PPN in temporary path block SETZM TMPPTH+.PTPPN+1 ; Insure zero word terminator MOVEI T3,TMPPTH ; and point to the block LOOKP2: HRLZI T3,(T3) ; Move path pointer to left half HRRI T3,FPATH(P4) ; Make BLT pointer to FPATH BLT T3,FPATH+.PTPPN+1+SFDLVL+1-1(P4) ; Move path to core block SKIPL T,T2 ; If RIB address positive, PUSHJ P,CFP2BK ; must be CFP, not block SKIPGE RIBLBN(P4) ; Block or CFP? MOVN T,RIBLBN(P4) ; Block. Get it. MOVEM T,RIBLBN(P4) ; and store T=log block in STR of RIB MOVE T1,T MOVE T,IOW ; T1=Block now, and T=IOWD MOVX T2,IO.FAC ; Set internal bits now MOVEM T2,IOSTS(P4) PUSHJ P,STRRED ; Go read the block JRST LKER6 ; Can't read RIB?? MOVE T1,RIBLBN(P4) ; Get back RIB address PUSHJ P,RIBCHK ; Validate RIB PJRST LKER6 ; Not a good RIB.. PUSHJ P,PTRCPY ; Copy some retrieval ptrs SETOM RIBFLG(P4) ; Set flag for reading first RIB MOVE T,BUF+RIBSTS ; File status bits MOVEM T,FILSTS(P4) ; Set channel file status PUSHJ P,SETBUF ; Go fix up data buffers MOVE T,BUF+RIBSIZ ; Size of file ADDI T,BLKSIZ-1 ; Pad up to next block IDIVI T,BLKSIZ ; Convert to blocks MOVEM T,FILEN(P4) ; and remember so we know EOF... LOOKP1: TLZN P4,1 ; Is this an ENTER? JRST CPOPJ1 ; No. LOOKUP is done. MOVX T,IO.WRT ; Yes. Set writing bit ORM T,IOSTS(P4) MOVI BLKSIZ+1,WDCNT(P4); Change BUFRED logic a little. Blocks ; are empty after 200 words, not before. MOVI DATBUF(P4),DATPTR(P4) ; and set up pointer JRST CPOPJ1 ; OK. He's all set up now. ; Here on RIB error LKER6: PUSHJ P,ECRLF MOVEI M,[ASCIZ/File /] PUSHJ P,MSG PUSHJ P,CHNPNT MOVEI M,[ASCIZ/ RIB error /] SETZM ERRFL ; Dont need CONI bits and status PUSHJ P,DEVER1 ; and complain HRRI T1,ERTRN% ; Bad RIB!! HRRM T1,BUF+EXLERC ; Ret error code in BUF too. POPJ P, ; Subroutine to do LOOKUP UUO on USRNAM,USREXT,USRPPN USRLOK: MOVPTH USRPTH,TMPPTH ; Move path to where we can diddle it MOVE T,CURLVL ; Get current level of nesting SETZM TMPPTH+.PTPPN+1(T) ; Insure zero terminator MOVE T,USRNAM ; Get filename HLLZ T1,USREXT ; and extension MOVE T2,USRCFP ; and CFP MOVEI T3,TMPPTH ; Point to path block MOVEI P4,DSK ; Point to DSK core block PJRST LOOKP ; Do it ; Subroutine to compute folded checksum of a word ; Call with (T) = word for which to compute checksum, ; (M) = checksum byte pointer from HOM block ; RET+0 always with (T2) = checksum CHKSUM: HRRI M,T ; Make byte pointer point to T LDB T1,[POINT 6,M,11] ; Get byte width from pointer MOVNS T1 ; T1 = -byte width of checksum TLZA M,770000 ; M = POINT width,T,35 CHKSU1: ADD T,T2 ; Add byte into remainder of word LDB T2,M ; Get next byte LSH T,(T1) ; and shift it out JUMPN T,CHKSU1 ; Continue until done POPJ P, ; ; Subroutine to try a RENAME UUO. ; Call P4=Channel adr of level to be modified ; C(BUF)= New RIB, BUF+RIBNAM=0 indicates delete, not rename ; As in monitor RENAMEs, LOOKUP must have been ; previously done to set up data.. ; ; Ret+0 Couldn't delete it for some strange reason ; Ret+1 File RIPped OFF ; ; Most AC's guaranteed to be destroyed... RENAM: SKIPN BUF+RIBNAM ; Deleting file? JRST RENAM0 ; Yes. No need to change RIB MOVE T,IOW ; Transfer word points to BUF MOVE T1,RIBLBN(P4) ; Get block # of first RIB PUSHJ P,STRWRT ; Go write over it JFCL ; Well shit. ; Here to re-write a new UFD RENAM0: MOVEI T,0 ; Offset into core block table RENAM3: SKIPN CORBLK(T) ; Hit end yet? JRST CPOPJ ; Yes, and no match, error CAME P4,CORBLK(T) ; Pointing to this core block? AOJA T,RENAM3 ; No, loop for rest MOVE P1,DATPTR(P4) ; Pointer to data SUBI P1,2 ; -2=Ptr to this UFD SKIPE T,BUF+RIBNAM ; Skip if deleting file JRST RENAM1 HRLI T,2(P1) HRRI T,0(P1) BLT T,DATBUF+BLKSIZ-3(P4) ; Move entire UFD down over this entry SETZM DATBUF+BLKSIZ-2(P4) ; Clean up ends SETZM DATBUF+BLKSIZ-1(P4) JRST RENAM2 ; and go write block RENAM1: MOVEM T,(P1) ; Put new name in UFD HLLZ T,BUF+RIBEXT HLLM T,1(P1) ; and new ext (leave CFP undisturbed) SKIPA ; Done. Change DATPRT if just rename ; (not delete) RENAM2: MOVEM P1,DATPTR(P4) ; Restore possibly changed pointer MOVE T,XIOWD(P4) ; IOWD for transfer MOVE T1,THISBL(P4) ; Block to overwrite MOVE U,THISU(P4) PJRST BLKWRT ; Subroutine to delete a file. ; Monitor LOOKUP-RENAME tried first, if anything goes wrong, ; file gets RIPped-OFF! ; Returns value of UBLKCT=number of blocks in file, unless ; LOOKUP fails or RIPOFF RENAME called in, set to -1. ; If F.DBAD set, delete only if file has monitor LOOKUP/ENTER failure DELFIL: PUSHJ P,INIDSK ; Make sure we got a disk MOVPTH USRPTH,TMPPTH ; Move path to where we can diddle it MOVE P4,CURLVL ; Get current level of nesting SETZM TMPPTH+.PTPPN+1(P4) ; Insure correct zero terminator MOVE T,USRNAM ; Get filename HLLZ T1,USREXT ; and ext SETZ T2, ; Third word in LOOKUP is zero MOVEI T3,TMPPTH ; Point to path block MOVE P4,CORBLK(P4) ; Point to correct core block SETZM BUF+RIBNAM ; Flag to RENAM in case of failure LOOKUP STR,T ; First try a LOOKUP so monitor sets tables JRST DELFI1 ; LOOKUP fails, definitely delete it TXZE F,F.DBAD ; File OK. Delete only bad ones? POPJ P, ; Yes. this file ok. dont delete JRST DELFI3 ; Skip error checks DELFI1: HRRZ T,T1 ; Get error code from LOOKUP CAIN T,ERFNF% ; File not found? POPJ P, ; Yes, can't delete what aint there DELFI3: HLRE T,T3 ; Get +blocks or -words JUMPGE T,DELFI2 ; Blocks. OK MOVMS T ; + words ADDI T,BLKSIZ-1 ; Round up to next block IDIVI T,BLKSIZ ; Convert to blocks DELFI2: MOVEM T,UBLKCT ; Remember blocks length of file. SETZB T,T1 RENAME STR,T ; and try to delete it SKIPA ; Can't JRST CPOPJ1 ; Excellent, excellent. SETOM UBLKCT ; Don't know file size DELFI4: TXNE F,F.MDEL ; Want only monitor RENAME? POPJ P, ; Yes, that's it PJRST RENAM ; Go RIP it OFF ; Here to delete a UFD.. Same call as DELFIL. DELUFD: PUSHJ P,INIDSK ; Get a disk PUSHJ P,SETUFD ; Set up UUOBLK POPJ P, ; Path exhausted LOOKUP STR,BUF ; Look for it JFCL SETZM BUF+RIBNAM MOVEI P4,MFD RENAME STR,BUF JRST DELFI4 ; Setup and then call RENAM JRST CPOPJ1 ; Got it! ; Subroutine to delete a file. Exactly like DELFIL, ; except monitor LOOKUP/RENAME not even tried. File ; Gets RIPped OFF no matter what. SATs are not updated. ; Not really a recommended subroutine, however, much ; faster than DELFIL.. Much. RIPFIL: PUSHJ P,USRLOK ; Look up file first JRST RIPFI1 ; Not there. Bad. TXZE F,F.DBAD ; OK. Only delete not OK ones? POPJ P, ; Yes. Better leave this one alone SKIPA T,BUF+RIBALC ; No. T=# of blocks allocated RIPFI1: SETO T, ; or -1 on lookup failure MOVEM T,UBLKCT MOVE P4,CURLVL ; Get current level of nesting MOVE P4,CORBLK(P4) ; and pointer to core block SETZM BUF+RIBNAM PJRST RENAM ; Go zap this file too. ; Subroutine to do buffered input, binary mode (e.g., returns one word each call) ; or allow dump mode input, IOWD in XIOWD+CHN'BLK ; Call DMPIN for dump, BUFRED for buffered ; P4=Channel adr. ; F.LEN set to ignore file length and give EOF return only ; when RIB pointers are exhausted ; Ret+0 EOF ; Ret+1 Word in AC 'CH' ; ; Note: There are no INITs and a channel doing buffered I/O ; can switch to dump at any time. If the buffered ; I/O was in the middle of a block, that block is lost ; and I/O proceeds with the next block. BUFRED: TLZA P4,1 ; Flags dump I/O DMPIN: TLO P4,1 JSP M,BUFSAV ; Save most AC's TLNE P4,1 ; Dump or buffered? JRST BUFRD5 ; Ignore word count in dump mode SOSLE WDCNT(P4) ; Any room left in core? JRST BUFRD2 ; Yep. BUFRD5: SOSGE FILEN(P4) ; File still got blocks left? TXNE F,F.LEN ; Ignore that fact? JRST .+2 ; Yes don't give EOF return JRST BUFEOF ; No. Give EOF ret now TXZ F,F.CSUM ; Assume not first block in group IGNORE: SOSLE BLKCNT(P4) ; Another contigious block in group? JRST BUFRD3 ; Yes. MOVE U,THISU(P4) ; Get last unit PUSHJ P,GETPTR ; No. Get next RIB pointer JUMPE P1,BUFEOF ; Done if no more pointers TXZE F,F.NEWR ; GETPTR find an extended RIB? SETOM RIBFLG(P4) ; Yes, flag it as such MOVEM P2,CLSCNT ; Remember # of clusters here. IMUL P2,STRBPC ; P2=# of contigious blocks MOVEM P2,BLKCNT(P4) LDB T1,STRCLP ; T1=cluster address MOVE P2,T1 ; Save it in P2 for CLSCHK IMUL T1,STRBPC ; Convert to blocks MOVEM T1,THISBL(P4) ; Remember block # MOVEM U,THISU(P4) ; and the unit it came from. SKIPLE FILEN(P4) ; Don't checksum if no more blocks TXO F,F.CSUM ; Checksum first block in group. HRRZ T,P4 CAIN T,DSK ; On channel DSK? TXNN F,F.OURS!F.TRB ; Yes. Need to check SATs? JRST BUFRD1 ; No to either. Skip it. BUFRD6: MOVE T,P2 ; T=cluster number PUSHJ P,CLSCHK ; Check it. JFCL SOSLE CLSCNT ; Loop for all clusters in group AOJA P2,BUFRD6 BUFRD1: AOSG RIBFLG(P4) ; Was this a RIB (set by LOOKP)? JRST IGNORE ; Yes. Ignore it MOVE T1,THISBL(P4) ; No. Get back block number ; Here with T1=block on unit, U=unit BUFRD4: MOVE T,IOSTS(P4) TXNE T,IO.WRT ; Writing this file? SETOM NOIO ; Yes. Don't bother to read then MOVX T,RIPABC TDNE T,FILSTS(P4) ; File always have bad checksum? TXZ F,F.CSUM ; If yes, dont try to. MOVE T,XIOWD(P4) ; T:=IOWD for moving data into core PUSHJ P,BLKRED ; Go read block JFCL ; Ignore error for now. MOVE T,IOSTS(P4) ; Are we really reading? TXNN T,IO.WRT ; ?? JRST BUFRD7 ; Yes. Keep what we got. PUSHJ P,REWRITE ; No. Were really writing JFCL ; Here when data in core, reset pointers BUFRD7: TLNE P4,1 JRST BUFRD2 ; Ignore these in dump I/O MOVI BLKSIZ,WDCNT(P4) ; Reset # of words left counter MOVI DATBUF(P4),DATPTR(P4) ; and pointer to data word ; Here if all ptrs OK, data in core. BUFRD2: TLZE P4,1 POPJ P, ; Thats all for dump I/O MOVE CH,SAVECH ; Restore CH in case writing ; (saved at entry by BUFSAV) MOVE T,IOSTS(P4) ; Check status to see if TXNE T,IO.WRT ; Reading or writing. MOVEM CH,@DATPTR(P4) ; Store CH if writing MOVE CH,@DATPTR(P4) ; Load CH if reading AOS DATPTR(P4) ; Increment pointer JRST CPOPJ1 ; and return to caller ; Here if next block contigious, dont need to read RIB ptrs BUFRD3: AOS T1,THISBL(P4) ; Set to read disk block after last MOVE U,THISU(P4) ; On same unit JRST BUFRD4 ; Here on EOF (FILEN ran out or zero pointer) ; set a few bits BUFEOF: MOVE T,IOSTS(P4) TXO T,IO.EOF ; Set EOF bits TXZ T,IO.FAC ; and zero active bit MOVEM T,IOSTS(P4) SETZM NOIO ; In case he had set it POPJ P, ; and give error ret ; Subroutine to output (re-write) last block just read on channel ; by DMPIN (or current block by BUFRED). ; Call P4=channel address... ; ; Ret+0 Didn't succeed... ; Ret+1 OK. Block ripped off. ; REWRIT: JSP M,BUFSAV ; Save the AC's MOVE T1,THISBL(P4) ; Get current (last) block MOVE U,THISU(P4) ; and unit MOVE T,XIOWD(P4) ; and new iowd to new data PJRST BLKWRT ; Zap! ; Subroutine to get next real ptr from core block ; Call P4=Addr of core block ; U=Last unit (incase no change of unit pointer) ; Return+0 always with: ; P1=Retrieval ptr or 0 if no more ptrs ; P2=Cluster count ; U=UDB address ; F.NEWR set in RH(F) if RIB pointers are extended ; GETPTR: TXZ F,F.NEWR ; Zero this flag on every entry MOVEI P1,10 ; Number of times to retry on ill unit MOVEM P1,TEMP GETPT1: SETZ P1, SKIPL P2,SAVRIB+RIBFIR(P4) ; P2:=Adr of next pointer JRST GETPT2 ; No more pointers MOVE P1,(P2) ; P1:=pointer AOBJN P2,.+1 MOVEM P2,SAVRIB+RIBFIR(P4) ; Adr of next pointer for next time GETPT2: LDB P2,STRCNP ; P2:= Cluster count JUMPN P2,CPOPJ ; Done if non-zero TXZN P1,RIPNUB ; Skip if new unit ptr JRST GETPT4 ; EOF pointer. Done now. HRRZ U,P1 ; Set U=new unit CAMLE U,HIGHU ; Within bounds? JRST GETPT3 ; Illegal unit MOVE U,STRUNI(U) ; Set U:=New unit UDB JRST GETPT1 ; and try again ; Here on EOF. All pointers done. Check for extended RIBs. GETPT4: SKIPN SAVXRA(P4) ; Got an extended RIB? JRST GETPT5 ; No. Set P2=0 and return LDB U,DEYRBU ; Get unit number from RIBXRA MOVE U,STRUNI(U) ; U=UDB for this unit LDB T1,DEYRBA ; Get cluster address within unit IMUL T1,STRBPC ; Convert to blocks MOVE T,IOW ; T=IOWD to BUF, read extended RIB PUSHJ P,BLKRED ; Go read a new RIB JRST GETPT5 ; Hmm. PUSHJ P,PTRCPY ; Copy them into core block TXO F,F.NEWR ; Tell caller I extended ptrs JRST GETPT1 ; and continue as if nothing happened. ; Here on illegal unit GETPT3: MOVEI M,[ASCIZ/ Illegal unit in RIB pointer file /] PUSHJ P,EMSG PUSHJ P,CHNPNT MOVEI M,[ASCIZ/ pointer = /] PUSHJ P,EMSG TXO P2,RIPNUB MOVE N,P2 PUSHJ P,OCTL12 MOVEI M,[ASCIZ/ = unit /] PUSHJ P,MSG MOVE N,U PUSHJ P,OCTPRT SOSLE TEMP ; Tried 10 times already? JRST GETPT1 ; No. Try to get another pointer MOVEI M,[ASCIZ/ Too many illegal unit pointers, EOF exit taken /] PUSHJ P,EMSG PUSHJ P,ECRLF GETPT5: SETZB P1,P2 ; Clear P1 and P2 and exit POPJ P, ; Subroutine to copy retrieval ptrs into core block ; Arg P4=Addr of core block PTRCPY: MOVE T,BUF+RIBFIR MOVEM T,SAVRIB+RIBFIR(P4) ; Store ptr to ptrs HRLZI T1,BUF(T) ; T1=Address of ptrs in BUF ,, 0 HRRI T1,SAVRIB+1(P4) ; Set to transfer them to SAVRIB BLT T1,SAVRIB+BLKSIZ-RIBENT-1(P4) MOVEI T1,SAVRIB+1(P4) ; First ptr is now at SAVRIB+1 HRRM T1,SAVRIB+RIBFIR(P4) ; So make ptr to ptrs right SETZM SAVXRA(P4) HRRZS T ; First word in RIB had ptr to ptrs CAIG T,RIBXRA ; Is this RIB old format? POPJ P, ; Yes. Before extended ribs. MOV BUF+RIBXRA,SAVXRA(P4) ; No. Store XRA (may still be zero) POPJ P, ; Subroutines to read one word from disk, UFD, MFD, or SFD ; Call PUSHJ P,R.xxx ; EOF return ; Normal return here ; R.MFD: MOVEI P4,MFD PJRST BUFRED R.UFD: MOVE P4,CURLVL ; Get current level SKIPA P4,CORBLK(P4) ; Get core block to use R.DSK: MOVEI P4,DSK PJRST BUFRED W.DSK==R.DSK ; To write, we use same code, but caller W.UFD==R.UFD ; Sets IO.WRT bit first so we know. DEFINE X (N), < EXP SFD'N > ; ; The following table gives the core block addresses that ; correspond to each level of nesting. ; EXP MFD CORBLK: EXP UFD I=1 REPEAT SFDLVL, < X (\I) I=I+1 > EXP 0 ; Subroutine to do CLOSE UUOs C.DSK: MOVEI CH,0 ; Write zeroes PUSHJ P,W.DSK POPJ P, ; Until the EOF occurs JRST C.DSK C.UFD: MOVEI CH,0 PUSHJ P,W.UFD POPJ P, JRST C.UFD ; Subroutine to convert a CFP in AC T ; Returns logical block number in T, ; Relative block in unit in T1, ; U=Unit UDB address ; T=-1 if illegal unit. CFP2BK: IDIV T,HOMSCU(U) ; T=Unit,T1=Supercluster in unit CAMLE T,HIGHU ; Above top? JRST CFP2B2 MOVE U,STRUNI(T) ; U=Unit UDB IMUL T1,HOMBSC(U) ; T1=Block in unit IMUL T,STRBPU ; T=# of first block on unit ADD T,T1 POPJ P, CFP2B2: SETO T, POPJ P, SUBTTL Lowest level disk I/O routines ; Subroutine to read or write one disk block ; Call T=IOWD to data, T1=block on unit, U=Unit UDB address, ; P4=Channel core block address ; ; Ret+0 I/O Errors. Full error diagnostic is printed at this level. ; Ret+1 Block read/written OK. ; ; Call with F.CSUM set to checksum block and compare to checksum ; in retrieval pointer in P1. Checksum error does not ; cause ret+0, but IO.CKS set in LH of IOSTS word. ; ; Call with F.DERR set if you expect to get hard read error. This ; causes error message to be suppressed (error flags still return ; error condition). Expressely for SYSINI to determine disk pack ; type by trying to read too large a block for various packs. ; Flag is reset to 0 every time. ; ; Call with NOIO = -1, and the actual I/O operation will be suppressed, ; (both USETI/O and INPUT/OUTPUT - CURPOS left unchanged) ; ; T,T1 destroyed, F.IO reset to 0 if reading(BLKRED), 1 if writing(BLKWRT) BLKRED: TXZA F,F.IO ; Set reading BLKWRT: TXO F,F.IO ; Set writing BLKRD0: TXZ F,F.TRY ; We try all I/O twice BLKRD1: MOVEM T,TIOW ; Get an immidiate AC and save IOWD JUMPL T1,TOBIG ; Negative blocks not nice. CAML T1,BLKUNI(U) ; Must be on unit.. JRST TOBIG ; Not. Fake IO.BKT... SKIPGE NOIO ; Need real I/O? JRST BLKRD4 ; No, skip USETX, I/O AOS T,CURPOS(U) ; Bump last block positioned to CAMN T,T1 ; Trying to read last block+1? JRST BLKRD2 ; Yes. No USETI/O required MOVEM T1,CURPOS(U) ; No. Reset new position MOVE T,XCHAN(U) ; Get proper channel SKIPN %SUSET ; Use SUSET.? JRST BLKRD6 ; No. Skip this HLLZS T ; Clear right half (was Z CHN,T) IOR T,T1 ; Yes. Add in block number TXNE F,F.IO ; Reading? TXO T,SU.SOT ; Writing. Set bit SUSET. T, ; Do UUO. JRST DIE001 ; God!!!! JRST BLKRD2 ; Skip USETI/O stuff ; Here to position using USETI/USETO BLKRD6: ; Use super USETI/USETO TXNN F,F.IO TLOA T,(USETI) ; Set for reading or writing TLO T,(USETO) HRRI T,T1 XCT T ; USETx CHN,T1 ; ; Here when unit in position, read block BLKRD2: MOVE T,XCHAN(U) TXNN F,F.IO TLOA T,(IN) ; Prepare for IN or OUT-put TLOA T,(OUT) SKIPA PUSHJ P,[ SKIPGE WENABLE POPJ P, MOVEI M,[ASCIZ/Write enable?/] PUSHJ P,OPER JRST DIE002 SETOM WENABLE POPJ P, ] HRRI T,TIOW SETZM TIOW+1 XCT T ; IN CHN,TIOW TXZA F,F.TMP ; Got it! TXO F,F.TMP ; Bad block.. PUSHJ P,GETUST ; Get units status now TXZN F,F.TMP ; Read succeed?? JRST BLKRD4 ; Yes. Go process data. ; Here on error in I/O transfer. Print msg, reset status and exit ; but always try twice before quitting (F.TRY) MOVE T1,XCHAN(U) TLO T1,(GETSTS) XCT T1 ; GETSTS CHN,T HRRM T,IOSTS(P4) ; Save it TXZ T,IO.ERR!IO.EOF ; Reset error flags HLL T,XCHAN(U) TLO T,(SETSTS) XCT T ; SETSTS CHN,BITS TXON F,F.TRY ; Tried once already? JRST BLKRD5 ; No. Try again TXZE F,F.DERR ; Yes. Expecting this? POPJ P, ; Yes. Return now SETOM ERRFL ; Print entire error status and CONI SOS ERRFL PJRST DEVERR ; No. Go print error msg and return BLKRD7: TXO F,F.CSUM ; Turn checksum bit back on BLKRD5: MOVE T,TIOW ; Prepare to try again MOVE T1,CURPOS(U) ; Set position request JRST BLKRD1 ; and try one more time ; Here when we got the data, now process it before returning BLKRD4: TXZ F,F.DERR ; Reset flag in case set MOVX T, ANDCAM T,IOSTS(P4) ; Clear all error bits AOSLE NOIO ; Supposed to read? TXZN F,F.CSUM ; Yes. Supposed to checksum it? JRST CPOPJ1 ; No. Return to him now. MOVE T,TIOW MOVE T,1(T) ; T=Word to checksum SKIPN M,STRCKP JRST CPOPJ1 ; Might be a unit not in a STR. PUSHJ P,CHKSUM ; Compute checksum LDB T1,STRCKP ; Get checksum from ptr CAMN T1,T2 ; Equality? JRST CPOPJ1 ; Yep. Got it now. MOVX T,IO.CKS ; No. Light err bit ORM T,IOSTS(P4) TXON F,F.TRY ; Tried once already? JRST BLKRD7 ; No. Try again SETOM ERRFL ; Don't give CONI stuff AOS (P) ; Yes. Give skip return anyway PJRST DEVERR ; and give error msg ; Subroutine to read or write a disk block relative to structure ; Call Identical to BLKRED/WRT, except T1=block on STR STRRED: TXZA F,F.IO STRWRT: TXO F,F.IO CAML T1,STRHGH ; Must be within STR... JRST TOBIG IDIV T1,STRBPU MOVE U,STRUNI(T1) ; Unit number within STR MOVE T1,T2 ; Remainder = block on unit JRST BLKRD0 ; Go read it. ; Here if block too large for unit, simulate IO.BKT error TOBIG: MOVEI T,IO.BKT ORM T,IOSTS(P4) ; Set IO.BKT bit in IOSTS PUSHJ P,GETUST ; Reset unit status SETOM ERRFL ; Print entire status plus CONI SOS ERRFL PJRST DEVERR ; Subroutine to get a unit's CONI status GETUST: LDB T,[POINT 4,XCHAN(U),12] ; Get channel number DEVSTS T, ; Ask monitor for CONI SETZ T, ; If error, use zero MOVEM T,UNISTS(U) ; Set status POPJ P, SUBTTL Assorted disk support routines ; Subroutine to find a disk block. ; Call P1=Relative address in block of key word ; P2=Contents of key word ; SETBLK=Block-increment to start search with, i.e., ; SETBLK+T4 = First block to start search with ; U=UDB first unit to begin search ; T4=Number of blocks to increment SETBLK for each read ; ; If SATFLG = 0, every T4 blocks are read. ; SATFLG >0, ignore blocks not set in DSKSAT ; i.e., read only if marked in SAT ; SATFLG <0, ignore blocks set in DSKSAT, ; i.e., read only if free blocks ; ; Ret+0 Entire STR searched, no match found ; Ret+1 SETBLK=Address of block ; U=Unit UDB ; SEARCH: ADDM T4,SETBLK ; Increment SETBLK first thing MOVE T1,SETBLK ; T1=New block to search CAML T1,BLKUNI(U) ; Still in unit? JRST SRCH3 ; No. Try next unit SKIPN SATFLG ; Want to check SATs? JRST SRCH2 ; No. Forget it PUSH P,T1 ; Save T1 IDIV T1,STRBPC ; Convert to clusters MOVE T,DSKSAT(U) ; T=Address of SAT table PUSHJ P,TSTONE ; See if set SKIPA T,[SKIPL SATFLG] ; Skip if want to read instn. MOVE T,[SKIPG SATFLG] ; Also instn for skip if want to read POP P,T1 ; Restore T1 XCT T ; Well, do we read it? JRST SEARCH ; No. Ignore the block. SRCH2: MOVE T,IOW ; Yes. Read it now PUSHJ P,BLKRED ; Go read it JRST SEARCH ; Ignore it if cant CAMN P2,BUF(P1) ; Match? JRST CPOPJ1 ; Yes. Got it! JRST SEARCH ; No match, try again SRCH3: HLRZ U,(U) ; Try the next unit SETZM SETBLK ; Start at block zero JUMPN U,SEARCH ; and try again. POPJ P, ; Unless no more units, exit ; Subroutine to make a user UFD/SFD ; Call USRPPN/USRPTH=Path to create one for ; ; Special kludge - Call MAKUF1 to create UFD/SFD in buffered mode. ; Will not change channel status with release or inits. ; (this specifically for /I code to make UFD's with) ; ; Ret+0 Can't. Error message given ; Ret+1 Got it. STR INITed and not released. MAKUFD: PUSHJ P,INIDSK ; Get a disk MAKUF1: PUSHJ P,SETUFD ; Setup BUF for UUO POPJ P, ; Path exhausted, return MOV BIGNUM,BUF+RIBQTF ; Set all quotas to infinity MOVEM T,BUF+RIBQTO SETZM BUF+RIBUSD ; No blocks used by user yet MOV <[RIPLOG!RIPDIR]>,BUF+RIBSTS ; This is a directory bit MOV UFDPRT,BUF+RIBPRV ; Set UFD privelliges CLOSE STR, ; Just in case ENTER STR,BUF ; Do it, mac! JRST MAKUF2 ; ENTER failed. Forget it CLOSE STR, STATO STR,IO.ERR ; All ok? JRST CPOPJ1 ; Yup. Got one now. MAKUF2: JSP M,TTYOUT PUSHJ P,CRLF PUSHJ P,UFDPNT MOVEI M,[ASCIZ/ UFD creation error: /] PUSHJ P,MSG HRRZ N,BUF+EXLERC PUSHJ P,OCTPRT PJRST CRLF2 ; Subroutine to setup BUF for extended LOOKUP/ENTER on UFD/SFD ; Assumes that USRPPN/USRPTH/CURLVL point to current UFD/SFD ; Ret+0 if path exhausted ; Ret+1 if path setup in BUF SETUFD: PUSHJ P,ZROBUF ; Zero entire UUO block MOVI EXLLEN,BUF+RIBFIR ; Set arg length MOVE T,USRPTH+.PTPPN ; Get PPN SKIPE CURLVL ; Still in PPN? JRST SETUF3 ; Nope, handle path special MOVEM T,BUF+RIBNAM ; Store PPN as name MOVSI T,'UFD' MOVEM T,BUF+RIBEXT ; Extension = 'UFD' MOV MFDPPN,BUF+RIBPPN ; PPN=MFD JRST CPOPJ1 ; Good return SETUF3: MOVSI T,USRPTH ; Get path from here HRRI T,TMPPTH ; and move it to here BLT T,TMPPTH+.PTPPN+1+SFDLVL+1-1 ; Move path block MOVEI T,TMPPTH MOVEM T,BUF+RIBPPN ; Set up pointer to path block MOVSI T,'SFD' ; MOVEM T,BUF+RIBEXT ; and extension MOVE T,CURLVL ; Get level of SFD nesting PUSH P,TMPPTH+.PTPPN(T) ; Save current SFD name SETZM TMPPTH+.PTPPN(T) ; and make this the last word of path POP P,BUF+RIBNAM ; File to create SKIPE BUF+RIBNAM ; Anything there? AOS (P) ; Yes, give good return POPJ P, ; and return ; Here to set up core blocks for data I/O. ; Call P4=Channel address SETBUF: SETZM BLKFIR(P4) MOVSI M,BLKFIR(P4) HRRI M,BLKFIR+1(P4) BLT M,BLKEND(P4) ; Zero entire data block MOVSI M,-BLKSIZ HRRI M,DATBUF-1(P4) MOVEM M,XIOWD(P4) ; IOWD for dump POPJ P, ; Subroutine to initialize BUF. Sets all words equal to contents ; of AC T. Ret+0 always... ZROBUF: SETZ T, ; Here to zero BUF BLTBUF: MOVEM T,BUF ; Set first word MOVE T,[BUF,,BUF+1] ; Set up BLT BLT T,BUF+BLKSIZ-1 ; Zap into entire block POPJ P, ; and return. SUBTTL Hard error listing ; Here on hard error. Prints summary of error. ; Call P4=channel address (for IOSTS word) ; U=UNIDDB (for unit, CURPOS, and UNISTS) ; Prints: ; File XXX.XXX [XX,XX] [Read|Write] error on DPAx, block x ; Status = NNNNNN IO.IMP+IO.DTE+... ; CONI = nnnnnn (device not ready)+(Search err)+(Etc...)+(PI channel=X) ; ; Set ERRFL to -2 to print full message ; -1 to suppress just CONI ; 0 to suppress extended status and CONI DEVERR: PUSHJ P,CRLF PUSHJ P,ECRLF PUSHJ P,CHNPNT MOVEI M,[ASCIZ/ Read/] TXNE F,F.IO MOVEI M,[ASCIZ/ Write/] PUSHJ P,MSG MOVEI M,[ASCIZ/ error on /] DEVER1: PUSHJ P,MSG MOVE M,DRIVE(U) PUSHJ P,PR6BIT ; Tell him where MOVEI M,[ASCIZ/, block /] PUSHJ P,MSG MOVE N,CURPOS(U) PUSHJ P,OCTPRT ; Print block currently being read PUSHJ P,EQUAL MOVE T2,CURPOS(U) PUSHJ P,PBNPRT ; Print physical address MOVEI M,[ASCIZ/ Status = /] PUSHJ P,EMSG MOVE N,IOSTS(P4) ; Status of this channel at last input PUSHJ P,HALF8 AOSLE ERRFL ; Suppress extended status and CONI? PJRST CRLF2 ; Yes MOVE N,IOSTS(P4) PUSH P,ZERO ; Start stack with zero TXZE N,IO.ACT PUSH P,[SIXBIT /IO.ACT/] TXZE N,IO.EOF PUSH P,[SIXBIT /IO.EOF/] TXZE N,IO.BKT PUSH P,[SIXBIT /IO.BKT/] TXZE N,IO.DTE PUSH P,[SIXBIT /IO.DTE/] TXZE N,IO.DER PUSH P,[SIXBIT /IO.DER/] TXZE N,IO.IMP PUSH P,[SIXBIT /IO.IMP/] TXZE N,IO.CKS PUSH P,[SIXBIT /IO.CKS/] MOVEI T2,SPC2 DEVER9: POP P,M JUMPE M,DVER10 PUSHJ P,(T2) MOVEI T2,PLUS PUSHJ P,PR6BIT ; Print all bits set in IOSTS JRST DEVER9 DVER10: AOSLE ERRFL ; Suppress the rest? PJRST CRLF2 ; Yes MOVEI M,[ASCIZ/ Coni = /] PUSHJ P,EMSG MOVE N,UNISTS(U) ; Get CONI word supplied by monitor PUSHJ P,OCTPRT ; Print it PUSH P,ZERO ; Start stack with zero word PUSHJ P,SETKTP ; Get internal controller type SKIPL T,EMSTBL(T) ; Get message table addr, skip for LH side TXZA F,F.TYPE ; Flag right side of message table TXO F,F.TYPE ; Ditto for left side MOVE N,UNISTS(U) ; Get status back MOVX T1,1B33 ; T1 shifts bits, first is bit 32 DEVER2: LSH T1,1 ; Increment to next bit JUMPE T1,DEVER5 ; Done after 33 TDNN N,T1 ; This bit set in status? AOJA T,DEVER2 ; No, try next TXNN F,F.TYPE ; Skip if left hand table SKIPA T2,(T) ; Get RH of table and skip HLRZ T2,(T) ; or LH TRNE T2,-1 ; Skip if place holder PUSH P,T2 ; Save message address on stack AOJA T,DEVER2 ; and loop for next DEVER5: MOVEI M,[ASCIZ/ (/] PUSHJ P,MSG DEVER6: POP P,M ; Get a msg address to print JUMPE M,DEVER7 ; Until done.. PUSHJ P,MSG MOVEI M,[ASCIZ/)+(/] PUSHJ P,MSG JRST DEVER6 DEVER7: MOVEI M,[ASCIZ/PI Channel=/] PUSHJ P,MSG LDB N,[POINT 3,UNISTS(U),35] PUSHJ P,OCTPRT PUSHJ P,RPAR PJRST CRLF2 ; CRLF & quit with EOF return ; Routine to return the internal controller type code used by ; DEVERR. This is not too hard in general, but it is quite ; difficult to tell the difference between an RH10 and an RH20 ; controller. If this ever becomes easier, the following code ; should be rewritten. Internal controller types are as follows: $FHKON==0 ; FH controller $DPKON==1 ; DP controller $R1KON==2 ; RH10 controller $R2KON==3 ; RH20 controller ; In addition, the following codes are defined from COMMOD and FILIO DIAKUN==7 ; DIAG. function to return controller type UNIKON==6 ; UDB offset of addr of KDB UNISYS==3 ; UDB offset of addr of next UDB in system RPXDI2==71 ; KDB offset of DATAI for controller R20KON==540 ; First RH20 device code SETKTP: LDB T,[POINTR UNIDES(U),DC.CNT] ; Get monitor controller type CAIN T,.DCCFH ; FH? JRST SETKT5 ; Yes CAIN T,.DCCDP ; DP? JRST SETKT6 ; Yes ; [076] At SETKTP + 4 1/2 CAIN T,.DCCFS ; [076] FS? JRST SETKT1 ; [076] Yes, that's on an RH10 MOVE T,CPUXX ; Get CPU type we're running on CAIE T,2 ; If not a KL, controller must be an JRST SETKT1 ; RH10 since RH20 requires KL MOVE T,[2,,T1] ; Setup for DIAG. UUO MOVEI T1,DIAKUN ; Function to return controller type MOVE T2,DRIVE(U) ; Physical unit in question DIAG. T, ; Do it JRST SETKT2 ; Gotta do it the hard way CAMGE T,[R20KON,,0] ; All RH20's are > R20KON SETKT1: SKIPA T,[$R1KON] ; Must be an RH10 MOVEI T,$R2KON ; RH20 POPJ P, ; Return ; ; Here when the DIAG. UUO failed to tell us anything. We must now ; resort to looking around in core (GAK!!!) ; SETKT2: MOVX T,%LDUNI ; Setup to look in the monitor GETTAB T, ; Get address of first UDB JRST SETKT1 ; Take a guess SETKT3: HLRZS T1,T ; Isolate the address JUMPE T,SETKT1 ; Guess if at end of chain without match PEEK T, ; Get UNINAM CAME T,DRIVE(U) ; Match with this one? JRST SETKT4 ; No, try next MOVEI T,UNIKON(T1) ; Point at UNIKON PEEK T, ; Get address of KDB MOVEI T,RPXDI2(T) ; Point at RPXDI2 in KDB PEEK T, ; Get it TDZ T,[DATAI 7] ; If not DATAI or DATAO, we TDNE T,[700077,,-1] ; can only guess JRST SETKT1 CAMGE T,[R20KON_6,,0] ; RH20? SKIPA T,[$R1KON] ; No, RH10 MOVEI T,$R2KON ; RH20 POPJ P, ; Return SETKT4: MOVEI T,UNISYS(T1) ; Point at UNISYS for current UDB PEEK T, ; Get new address JRST SETKT3 ; and look SETKT5: SKIPA T,[$FHKON] ; An FH controller SETKT6: MOVEI T,$DPKON ; or a DP POPJ P, ; Return ; The CONI bit tables have one entry for every bit in the ; CONI word (minus PI assignment bits) and point to the message ; for that bit. To save space, one controller uses one half ; of the table and another uses the other half. These tables ; are in turn pointed to by entries in EMSTBL which is indexed ; by the internally defined controller type number (see SETKTP). ; If bit 0 of EMSTBL is set for an entry, the corresponding ; controller message table is in the left half. EMSTBL: XWD 400000,FHEMS ; Pointer to FH controller CONI bits XWD 0,DPEMS ; Pointer to DP controller CONI bits XWD 400000,RH1EMS ; Pointer to RP (RH10) controller CONI bits XWD 0,RH2EMS ; Pointer to RP (RH20) controller CONI bits ; ; ; Table for FH,,DP CONI bits FHEMS: DPEMS: EM27,,EM21 ; Bit 32 EM20,,EM20 ; Bit 31 EM19,,EM19 ; Bit 30 EM11,,EM18 ; Bit 29 EM15,,EM17 ; Bit 28 EM12,,EM16 ; Bit 27 EM26,,EM15 ; Bit 26 EM25,,EM14 ; Bit 25 EM24,,EM13 ; Bit 24 EM9 ,,EM12 ; Bit 23 EM14,,EM11 ; Bit 22 EM23,,EM10 ; Bit 21 EM22,,EM9 ; Bit 20 EM10,,EM8 ; Bit 19 EM7 ,,EM7 ; Bit 18 0,,EM3 ; Bit 17 0,,EM2 ; Bit 16 0,,EM1 ; Bit 15 0,,EM0 ; Bit 14 0,,0 ; Bit 13 0,,0 ; Bit 12 0,,0 ; Bit 11 0,,0 ; Bit 10 0,,0 ; Bit 9 0,,0 ; Bit 8 0,,0 ; Bit 7 EM6 ,,0 ; Bit 6 EM5 ,,0 ; Bit 5 EM4 ,,0 ; Bit 4 0,,0 ; Bit 3 0,,0 ; Bit 2 0,,0 ; Bit 1 0,,0 ; Bit 0 ; Table for RH10,,RH20 CONI bits RH1EMS: RH2EMS: EM27,,EM27 ; Bit 32 EM20,,EM40 ; Bit 31 EM28,,EM41 ; Bit 30 EM29,,EM42 ; Bit 29 EM30,,EM28 ; Bit 28 0,,EM43 ; Bit 27 0,,EM44 ; Bit 26 EM9 ,,EM45 ; Bit 25 EM31,,EM29 ; Bit 24 EM32,,EM32 ; Bit 23 EM33,,EM35 ; Bit 22 EM19,,EM46 ; Bit 21 EM35,,EM47 ; Bit 20 EM36,,EM36 ; Bit 19 EM37,,EM37 ; Bit 18 EM12,,0 ; Bit 17 EM26,,0 ; Bit 16 EM2 ,,0 ; Bit 15 0,,0 ; Bit 14 0,,0 ; Bit 13 0,,0 ; Bit 12 0,,0 ; Bit 11 EM38,,0 ; Bit 10 EM39,,0 ; Bit 9 0,,0 ; Bit 8 0,,0 ; Bit 7 EM48,,0 ; Bit 6 EM49,,0 ; Bit 5 EM50,,0 ; Bit 4 EM51,,0 ; Bit 3 0,,0 ; Bit 2 EM52,,0 ; Bit 1 EM53,,0 ; Bit 0 ; and the error messages themselves: EM0: ASCIZ/*Cntrl wd par err*/ EM1: ASCIZ/*Sector par err*/ EM2: ASCIZ/*Chn data par err*/ EM3: ASCIZ/*Disk wd par err*/ EM4: ASCIZ/Unit is a drum/ EM5: ASCIZ/Sector 80/ EM6: ASCIZ/Low safe area/ EM7: ASCIZ/Search done/ EM8: ASCIZ/*End of cylinder*/ EM9: ASCIZ/*Pwr failure*/ EM10: ASCIZ/*Search err*/ EM11: ASCIZ/*Data late*/ EM12: ASCIZ/*No such memory*/ EM13: ASCIZ/*Par err*/ EM14: ASCIZ/*Not ready*/ EM15: ASCIZ/*Ill write*/ EM16: ASCIZ/Ill DATAO/ EM17: ASCIZ/*Sector addr err*/ EM18: ASCIZ/*Surface addr err*/ EM19: ASCIZ/Cntrl wd written/ EM20: ASCIZ/Busy/ EM21: ASCIZ/*Interrupt*/ EM22: ASCIZ/*Unit err*/ EM23: ASCIZ/*Track-sector err*/ EM24: ASCIZ/*Dev par err*/ EM25: ASCIZ/*Data par err*/ EM26: ASCIZ/*Cntrl wd par err*/ EM27: ASCIZ/*Done*/ EM28: ASCIZ/Attention/ EM29: ASCIZ/Reg access err/ EM30: ASCIZ/Cont bus overrun/ EM31: ASCIZ/Ill cmd/ EM32: ASCIZ/Drive response err/ EM33: ASCIZ/DTC overrun/ EM35: ASCIZ/Chn error/ EM36: ASCIZ/Exception/ EM37: ASCIZ/Data bus par err/ EM38: ASCIZ/SD reg access err/ EM39: ASCIZ/Ill fnc code/ EM40: ASCIZ/PCR full/ EM41: ASCIZ/Attention interupt enabled/ EM42: ASCIZ/SCR full/ EM43: ASCIZ/Massbus enabled/ EM44: ASCIZ/Data overrun/ EM45: ASCIZ/Chn ready/ EM46: ASCIZ/Short wd cnt/ EM47: ASCIZ/Long wd cnt/ EM48: ASCIZ/22 bit chn/ EM49: ASCIZ/Chn pulse/ EM50: ASCIZ/Chn active/ EM51: ASCIZ/CC inhibit/ EM52: ASCIZ/CB full/ EM53: ASCIZ/AR full/ SUBTTL SAT block I/O processing routines ; Subroutine to read/write disk SATs (DSKSAT) ; Ret+0 Error ; Ret+1 Got 'em ; ; Each SAT block on a unit is physically located near the clusters ; which it represents. Therefore, only the first block of each ; group of SAT.SYS contains the SAT; the rest of the blocks in each ; group are unused (and are usually -1). Furthermore, each group ; in SAT.SYS contains precisely one cluster. ; ; The SATs are read in such that the unused words in each SAT ; block are compressed, i.e., the first word of the second SAT ; is adjacent to the last word of the first SAT in core. No ; attempt is made to compress the unused bits in the last word ; of each SAT. RDSAT: TDZA T,T WTSAT: SETO T, MOVEM T,WTFLAG ; 0 if reading, -1 if writing JUMPE T,RDSAT4 ; Jump if reading PUSHJ P,STRMNT ; Is STR mounted? JRST ERR016 ; Yes, can't do this RDSAT4: MOVSI T,'SAT' ; Filename to lookup MOVSI T1,'SYS' ; and extension HLRZ U,UNIDDB ; Point to UDB for first unit MOVN T2,HOMSAT(U) ; Get -block number of RIB MOVE T3,SYSPPN ; and PPN ([1,4]) MOVEI P4,DSK ; Point to core block to use PUSHJ P,LOOKP ; LOOKUP SAT.SYS POPJ P, ; Propagate error to caller MOVEI U,UNIDDB ; Setup for reading SATs from each unit RDSAT0: HLRZ U,(U) ; Get next unit in structure JUMPE U,CPOPJ1 ; Return at end of list SKIPE WTFLAG ; If reading, allocate core first JRST RDSAT2 PUSHJ P,SATADD ; Allocate core for all SATs on unit MOVEM T,DSKSAT(U) ; Remember where it starts RDSAT2: MOVE P1,HOMSPU(U) ; P1 counts SATs on unit MOVE T,DSKSAT(U) ; Get address of start of SATs SOJ T, MOVN T1,UNIWPS(U) HRL T,T1 ; T=-WPS,,Address of SAT-1 (IOWD) ; ; Here to actually read all SATs for this unit into core. ; By setting NOIO for all but every (blocks/cluster) blocks, ; we effectively skip all but the first block in every ; group (=1 cluster) thus reading in the correct block as ; the SAT. ; RDSAT1: MOVEM T,XIOWD+DSK ; Store for input routines MOVE T1,HOMBPC(U) ; T1=Blocks/cluster RDSAT3: CAIN T1,1 ; At the 1st block of next cluster yet? SKIPE WTFLAG ; Yes. Writing?? SETOM NOIO ; No to either. Dont bother disks PUSHJ P,DMPIN ; Read blocks SOJG T1,RDSAT3 ; Loop until next real SAT is read SKIPE WTFLAG ; Writing? PUSHJ P,REWRIT ; Yes. Write over last block (the SAT..) JFCL SOJE P1,RDSAT0 ; For HOMSPU times, then go to next unit ADD T,UNIWPS(U) ; Inc to next SAT on this unit JRST RDSAT1 ; and read it. ;SUBROUTINE TO SET IN OURSAT THE BITS FOR BLOCKS POINTED TO BY BAT SETBAT: JSP M,SAVE3 ;SAVE P1-P3 MOVEI T,SETBTU ;CALL SETBTU ONCE FOR EACH UNIT IN STR PJRST DOALLU ;HERE WITH U=UDB SETBTU: PUSHJ P,BATCHK ;READ BAT BLOCK POPJ P, LDB P1,BAYNBR ;REGIONS FOUND BY MAPPER ADD P1,BUF+BAFCNT ;PLUS REGIONS FOUND BY MONITOR HRRZ P2,BUF+BAFFIR ;POINT TO FIRST PAIR +1 ADDI P2,BUF+1 STBTU2: LDB P3,BAYNBB ;NUMBER OF BLOCKS IN REGION ADDI P3,1 LDB P4,BAYELB ;GET THE BLOCK NUMBER MOVE T1,-1(P2) ;OLD STYLE BAT OR NEW? TRNN T1,BAPNTP HRRZ P4,(P2) ;OLD, OOPS WE DID IT WRONG STBTU1: MOVE T1,BLKUNI(U) ;BLOCKS ON THIS UNIT IDIV T1,STRBPC ;CLUSTERS ON THIS UNIT MOVE T1,BLKUNI(U) ;T2=NUMBER OF BLOCKS NOT IN ANY CLUSTER SUBI T1,1(T2) ;T1=LAST BLOCK OF LAST REAL CLUSTER CAMLE P4,T1 ;SKIP IF BLOCK IS WITHIN A REAL CLUSTER JRST STBTU9 ;NO, NEVER MIND MOVE T1,P4 ;CONVERT BLOCK TO CLUSTER IDIV T1,STRBPC HRRZ T,OURSAT(U) ;POINT TO IN-CORE SAT PUSHJ P,MRKONE ;SET THE BIT JFCL ;IGNORE IF ALREADY SET ADDI P4,1 ;BUMP BLOCK NUMBER SOJG P3,STBTU1 ;LOOP FOR EACH BLOCK IN REGION STBTU9: ADDI P2,2 ;POINT TO NEXT PAIR SOJG P1,STBTU2 ;LOOP FOR EACH PAIR POPJ P, ; Subroutine to build a SAT in core (OURSAT) ; by reading all files on the disk. ; Call with UNIDDB INIT'ed to structure ; F.RALL set in LH(F) to read all blocks ; F.QUICK set in RH(F) to go quickly, sets NOIO to BLKRED ; ;RET+0 always BLDSAT: MOVEI T,[PUSHJ P,SATADD ; Allocate core for units SAT MOVEM T,OURSAT(U) ; Remember where it starts PUSHJ P,MRKSAT ; Mark unused bits at end of SATs POPJ P, ] PUSHJ P,DOALLU ; Allocate all units TXO F,F.OURS ; Tell DMPIN to be setting bits in OURSAT ; Now read all files BLDST3: PUSHJ P,NXTPPN ; Get next PPN JRST BLDST1 ; None left, return BLDST4: TXZ F,F.LEN ; Use length PUSHJ P,NXTFIL ; Get next file JRST BLDST3 ; None left, try next PPN PUSHJ P,USRLOK ; Lookup the file JRST BLDST4 ; Ignore bad files TXO F,F.LEN ; Don't trust file length; wait for last ptr BLDST5: MOVEI P4,DSK ; Always do reads on channel DSK TXNE F,F.QUICK ; Quick form? SETOM NOIO ; Yes. Fix SATs, but dont actually ; read blocks or checksum them. PUSHJ P,DMPIN ; Read a block of the file MOVE T,IOSTS+DSK ; Get status after read TXNE T,IO.EOF ; Hit end? JRST BLDST4 ; Yes. Get next file TXNN F,F.QUICK ; If quick mode, TXNN F,F.RALL ; or if not reading all blocks JRST .+2 ; Force another cluster group JRST BLDST5 ; Otherwise skip it SOSGE T1,BLKCNT+DSK ; Compute number blocks remaining MOVEI T1,0 ; If negative, use zero SUB T1,FILEN+DSK ; Subtract number from file length MOVNM T1,FILEN+DSK ; But that makes it negative SETZM BLKCNT+DSK ; Zero blocks remaining in current group JRST BLDST5 ; and loop for rest of file BLDST1: TXZ F,F.OURS POPJ P, ; Routine to mark the unused bits in the last word of every SAT ; for this unit. ; ; Call with T = address of first SAT ; U = UDB address for this unit MRKSAT: PUSHJ P,SAVALL ; Save 'em all for safety MOVEI P1,-1(T) ; Save addr-1 of first SAT MOVE P2,BLKUNI(U) ; Get blocks/unit IDIV P2,HOMBPC(U) ; Compute number of full clusters on unit SUBI P2,1 ; Compute last cluster address SETOM P4 ; Pointer to last cluster in SAT MRKST1: CAML P4,P2 ; Done all SATs yet? POPJ P, ; Yes, all finished MOVE T,P1 ; Addr-1 of this SAT for MRKEND MOVE T1,UNICPS(U) ; Assume full SAT (not last) ADD P4,T1 ; Compute last cluster in this SAT CAMG P4,P2 ; Larger than last cluster? JRST MRKST2 ; No, no correction necessary ADD T1,P2 ; Compute real number of clusters by SUB T1,P4 ; Subtracting difference between P2 and P4 MOVE P4,P2 ; Setup for next time around loop MRKST2: PUSHJ P,MRKEND ; Mark bits in end of this SAT ADD P1,UNIWPS(U) ; Point to start of next SAT JRST MRKST1 ; and loop for next one ; Routine to mark the unused bits in the last word of a SAT ; ; Call with T = address of SAT - 1 ; T1 = Actual number of clusters in this SAT ; U = UDB address of this unit MRKEND: PUSH P,T ; Save addr of start of SAT IDIVI T1,^D36 ; Compute word index and remainder ADDI T,(T1) ; Point to last full word in SAT JUMPE T2,MRKEN1 ; Done if SAT ends on a word boundary MOVEI T,1(T) ; Partial word requires correction MOVNI T2,-1(T2) ; Compute -number containing bits MOVX T1,1B0 ; Set the sign bit ASH T1,(T2) ; Form mask for used bits in last word SETCAM T1,(T) ; Set unused bits in last word MRKEN1: POP P,T1 ; Retrieve addr-1 of SAT ADD T1,UNIWPS(U) ; Compute addr of last word of SAT block MRKEN2: CAML T,T1 ; Need to fill rest of block? POPJ P, ; No, return now MOVEI T,1(T) ; Bump address by one SETOM (T) ; Fill word with ones JRST MRKEN2 ; and loop for rest of block ; Subroutine to count free blocks in a SAT ; Call U=Unit UDB ; ; Ret+0 Always, N=Number of free blocks CNTSAT: JSP M,SAVE3 SETZB P1,P2 ; P1 counts SATs within unit MOVN P3,UNIWPS(U) ; P2 counts free blocks HRL P3,DSKSAT(U) MOVSS P3 ; P3=AOBJN ptr to SAT CNTST1: CAML P1,HOMSPU(U) ; Finished all SATs on unit? JRST PNTST2 ; Yes. Quit MOVE N,P3 ; Set N = AOBJN ptr PUSHJ P,ZBITS ; Count zero bits IMUL N,STRBPC ; 1 bit = BPC blocks ADDM N,P2 ; Tally blocks ADD P3,UNIWPS(U) ; Point to next SAT now AOJA P1,CNTST1 ; To next SAT and go. ; Subroutine to see if all SATs for a STR are in core ; ; Ret+0 NOPE.. ; Ret+1 Yup, I hope (at least core has been allocated for them..) ; SATINC: MOVEI U,UNIDDB HLRZ U,(U) JUMPE U,CPOPJ1 ; Made it all the way through, OK SKIPN T,DSKSAT(U) POPJ P, MOVE T1,UNIWPS(U) IMUL T1,HOMSPU(U) ADD T,T1 CAMLE T,.JBFF POPJ P, JRST SATINC+1 ; Loop for all SATs. ; Subroutine to allocate core for a SAT on a unit ; Ret+0 with T=Address of SAT SATADD: MOVE T,UNIWPS(U) ; Words needed for one SAT IMUL T,HOMSPU(U) ; Times SATs on unit PJRST CORGRB ; Get core for unit SATs and return ; Subroutine to set a bit in a SAT table (and SAT) ; Call T=Adr of SAT table ; T1=Cluster number within unit ; U=UDB ; ; Ret+0 If bit already set ; Ret+1 If bit not already set MRKONE: PUSHJ P,TSTONE ; Set if already set AOS (P) ; No. Set for skip return MOVNS T3 ; -Number of places to shift ROT T1,(T3) MOVEM T1,(T) POPJ P, ; Subroutine to zero a bit in a SAT table ; Call T=Adr of SAT table ; T1=Cluster number within unit ; U=UDB ; ; Ret+0 If bit already zero ; Ret+1 If bit was one, now it is zero MRKZRO: PUSHJ P,TSTONE ; See if already set SKIPA ; Not, which is not what we expect AOS (P) ; Already set. Give skip return MOVNS T3 ; -number of places to shift TLZ T1,400000 ; Make sure bit is zero ROT T1,(T3) ; Rotate it back to normal position MOVEM T1,(T) ; Put bit back into table POPJ P, ; and return ; Subroutine to count zero bits in a table ; Call N=AOBJN pointer to table ; Ret+0 Always, N=Number of zero bits ZBITS: JSP M,SAVE3 ; Get three AC's SETZ P1, ; Zero one to count zero bits ZBITS1: MOVE P2,(N) ; Get some data into P2 SETCA P2, ; Complement word JUMPE P2,ZBITS0 ; Must have been all ones. ZBITS2: SETCA P2, ; Back to normal JFFO P2,.+3 ; Count leading zeroes ADDI P1,^D36 ; Must have been all zeroes JRST ZBITS0 SETCA P2, ; Complement word again ADDI P1,(P3) ; Cound leading zeroes LSH P2,(P3) ; Shift them right off the end JFFO P2,.+2 ; Now cound leading ones JRST ZBITS0 LSH P2,(P3) ; and shift them out too JRST ZBITS2 ; Loop for all bits ZBITS0: AOBJN N,ZBITS1 ; Go to next word MOVE N,P1 ; Until done. Put answer into N POPJ P, ; and return ; Subroutine to determine if a bit set in a SAT table ; Call T=Adr of table ; T1=Cluster within unit ; U=UDB Adr ; ; Ret+0 Bit not set ; Ret+1 Bit is set ; ; Always T1=word contining bit with bit rotated to sign bit ; T3=Number of bits rotated TSTONE: IDIV T1,UNICPS(U) ; T1=SAT number, T2=Index of cluster in SAT IMUL T1,UNIWPS(U) ; T1=# of words to this SAT from beg. ADD T,T1 ; T=Beginning of the SAT we want IDIVI T2,^D36 ; T2=Index in SAT, T3=Pos in word ADD T,T2 ; T=Adr of word containing bit MOVE T1,(T) ; T1=word ROT T1,(T3) ; Rotate desired bit into sign bit TLOE T1,400000 ; Skip if not set and set for caller AOS (P) ; Give skip return POPJ P, ; Subroutine to print summary of number of cluster which are ; lost, free, or multiply used. ; Call with P4 set to one of the following values: $PRLST==2 ; Print lost, free, and multiply used clusters $PRFRE==1 ; Print free and multiply used clusters $PRMLT==0 ; Print only multiply used clusters PRALL: SETOM TEMP ; TEMP counts clusters MOVEI U,UNIDDB ; Setup for all units PRALL1: HLRZ U,(U) ; Move to next unit in str JUMPE U,PRALL5 ; At end of chain MOVE T1,HOMSPU(U) ; SATs per unit MOVEM T1,TEMP2 ; Save for later check SETZM T1 ; T1 is cluster offset for this sat ; ; Here to setup for each SAT on a unit ; PRALL2: PUSHJ P,BLDPTR ; Build byte pointer for this SAT PRALL3: PUSHJ P,GETCLS ; Get cluster for this unit,SAT JRST PRALL4 ; If no more in this SAT PUSHJ P,PRTCLS ; Print the one we found JRST PRALL3 ; and loop for next one ; ; Here at end of current SAT. If more on unit, do them, else ; move to next unit ; PRALL4: ADDI T1,1 ; Bump T1 by 1 CAMGE T1,TEMP2 ; Done all SATs for this unit? JRST PRALL2 ; Nope, loop for next one JRST PRALL1 ; Move to next unit ; ; Here when all units done. Print totals and loop for next ; type, if any. ; PRALL5: AOSG N,TEMP ; Increment count (start at -1) JRST PRALL6 ; If none found MOVEI M,[ASCIZ/ Total number = /] ; PUSHJ P,MSG ; PUSHJ P,DECPRT ; Print number found JRST PRALL7 ; PRALL6: MOVEI M,[ASCIZ/ There are no /] PUSHJ P,MSG ; MOVE M,HEDMSG(P4) ; Get type message PUSHJ P,MSG ; PRALL7: PUSHJ P,CRLF3 ; SOJGE P4,PRALL ; Loop for next type, if any POPJ P, ; ; Routine to setup OURPTR, DSKPTR, TRBPTR, and CLSCNT for this ; SAT. Call with (T1) = SAT number ; RET+0 always with pointers setup BLDPTR: PUSH P,T1 ; Save T1 IMUL T1,UNIWPS(U) ; Compute word offset MOVSI T,(POINT 1,0) ; HRR T,OURSAT(U) ; ADDI T,(T1) ; POINT 1,OURSAT+SAT offset MOVEM T,OURPTR ; HRR T,DSKSAT(U) ; ADDI T,(T1) ; POINT 1,DSKSAT+SAT offset MOVEM T,DSKPTR ; HRR T,TRBSAT(U) ; ADDI T,(T1) ; POINT 1,TRBSAT+SAT offset MOVEM T,TRBPTR ; MOVE T,UNICPS(U) ; Get clusters/SAT MOVEM T,CLSCNT ; CLSCNT counts sats MOVEM T,TEMP1 ; SOS TEMP1 ; TEMP1 = CLSCNT-1 for comparison POP P,T1 ; Restore T1 POPJ P, ; ; Routine to find the next cluster in error of specified type. ; Call with (P4) = type to do, (T1) = SAT number ; SAT. ; RET+0 if no more clusters in this SAT ; RET+1 with cluster in T GETCLS: PUSH P,T1 ; Save T1 across call PUSHJ P,@ROUTIN(P4) ; Get cluster of proper type JRST T1POPJ ; Restore T1 and return POP P,T1 ; Restore T1 MOVE T,TEMP1 ; # clusters/SAT - 1 SUB T,CLSCNT ; T = cluster offset in this SAT MOVE N,T1 ; IMUL N,UNICPS(U) ; Compute cluseter offset for this SAT ADD T,N ; T = cluster offset in this unit MOVE N,HOMLUN(U) ; Get logical unit IMUL N,STRBPU ; IDIV N,STRBPC ; N = cluster # 0 on this unit ADD T,N ; T = cluster on this unit JRST CPOPJ1 ; Return success ; Routine to print the cluster number in T ; Call with (T) = cluster number, (P4) =type of cluster ; RET+0 always PRTCLS: AOSE TEMP ; Count bad clusters JRST PRTCL1 ; If some already seen MOVEI M,[ASCIZ/ The following are /] ; PUSHJ P,MSG ; Print start of header MOVE M,HEDMSG(P4) ; Get rest of message PUSHJ P,MSG ; PUSHJ P,CRLF2 ; PRTCL1: MOVEI N,(T) ; MOVEI T,6 ; PUSHJ P,OCTZRO ; Print as zero filled octal PUSHJ P,SPC2 ; MOVE T2,TEMP ; Get number found so far ADDI T2,1 ; IDIVI T2,^D15 ; Print 15 per line JUMPN T3,CPOPJ ; PJRST CRLF ; Print CRLF and return ; Routines to find the next cluster of the specified type. Called ; via PUSHJ through the dispatch table ROUTIN indexed by type ; of cluster to find. ; ; Free = set in OUTSAT but not in DSKSAT DFREE: SOSGE CLSCNT ; More left? POPJ P, ; No. Try another unit ILDB T,OURPTR ILDB T1,DSKPTR JUMPE T,DFREE ; Forget it if not in OURSAT JUMPN T1,DFREE ; Set in DSKSAT? Should be JRST CPOPJ1 ; Nope. Got one ; Lost = Set in DSKSAT but not in OURSAT DLOST: SOSGE CLSCNT ; More left? POPJ P, ; No. Try another unit ILDB T,OURPTR ILDB T1,DSKPTR JUMPE T1,DLOST ; Forget it if not in DSKSAT JUMPN T,DLOST ; Set in OURSAT? Should be JRST CPOPJ1 ; Nope. Got one ; Mult = Set in TRBSAT DMULT: SOSGE CLSCNT ; More left? POPJ P, ; No. Try another unit ILDB T,TRBPTR JUMPE T,DMULT ; Forget it if not set in TRBSAT JRST CPOPJ1 ; Got one ; Dispatch table to routines to find the proper type of cluster. ; Must be in the same order as the values of $PRLST, $PRFRE, $PRMLT. ROUTIN: DMULT DFREE DLOST ; Table of messages associated with each type of cluster. Order is the ; same as that of ROUTIN. HEDMSG: [ASCIZ/multiply used clusters (belonging to more than one file)/] [ASCIZ/free clusters (not marked in use, but in some file)/] [ASCIZ/lost clusters (marked in use, but in no file)/] ; Subroutine to set bit in our SAT and check other SATs ; Call T=Cluster within unit ; U=UDB address ; If F.TRB set in LH(F), will look for trouble, otherwise, will just ; mark bits in OURSAT and return. ; CLSCHK: JSP M,SAVE3 ; Save P1,P2,P3 MOVE P1,T TXNN F,F.TRB ; Looking for trouble? JRST MARKIT ; No. Just mark OURSAT HRRZ T,TRBSAT(U) ; T=Adr of 1st trouble SAT on this unit MOVE T1,P1 ; T1=cluster within unit PUSHJ P,TSTONE ; See if bit set in trouble SAT JRST NOTRB ; No.. PUSHJ P,MULT ; Yes. Print multiply used and set trouble bit MARKIT: HRRZ T,OURSAT(U) MOVE T1,P1 PUSHJ P,MRKONE ; Set our SAT, but dont care if already set JFCL TXNN F,F.TRB ; Looking for trouble? JRST CPOPJ1 ; No. Just marking, done. JRST LKFREE ; See if cluster is free NOTRB: MOVE T1,P1 HRRZ T,OURSAT(U) PUSHJ P,MRKONE ; Set bits in our SAT PUSHJ P,MULT ; Already set, print and set trouble bit LKFREE: MOVE T1,P1 HRRZ T,DSKSAT(U) PUSHJ P,TSTONE ; See if bit set in disk SAT PUSHJ P,FREE ; No. Cluster is free JRST CPOPJ1 ; Yes. All is ok now.. MULT: MOVE T1,P1 HRRZ T,TRBSAT(U) PUSHJ P,MRKONE JFCL TXO F,F.MULT ; Remember this SKIPA M,[[ASCIZ/multiply-used cluster/]] FREE: MOVEI M,[ASCIZ/used but not marked in SAT/] PUSH P,M PUSHJ P,ECRLF PUSHJ P,CHNPNT MOVEI M,[ASCIZ/ cluster /] PUSHJ P,MSG MOVE N,HOMLUN(U) IMUL N,STRBPU IDIV N,STRBPC ADD N,P1 ; N=Cluster number PUSH P,N PUSHJ P,OCTPRT ; MOVEI M,[ASCIZ . = block .] PUSHJ P,MSG POP P,N IMUL N,STRBPC PUSHJ P,OCTPRT ; PUSHJ P,SPC2 POP P,M PUSHJ P,EMSG PJRST CRLF ; Subroutine to print a units SAT blocks ; Just like CNTSAT, but prints them too. ; Call U=Unit ; ; Ret+0 always, N= number of blocks free on unit ; PNTSAT: JSP M,SAVE3 PUSHJ P,FORM MOVEI M,[ASCIZ/SAT blocks for /] PUSHJ P,MSG SKIPN M,HOMLOG(U) MOVE M,DRIVE(U) PUSHJ P,PR6BIT PUSHJ P,CRLF SETZB P1,P2 ; P1=Relative SAT in unit, MOVN P3,UNIWPS(U) ; P2= Blocks free tally HRL P3,DSKSAT(U) MOVSS P3 ; P3=AOBJN pointer PNTST1: CAML P1,HOMSPU(U) JRST PNTST2 MOVEI M,SATMSG PUSHJ P,MSG MOVE N,P1 PUSHJ P,OCTPRT ; Print relative SAT PUSHJ P,SPC2 MOVE N,P3 PUSHJ P,ZBITS ; Count zero bits IMUL N,STRBPC ADDM N,P2 ; Tally blocks PUSHJ P,DECPRT MOVEI M,FREMSG ; Print free blocks this SAT PUSHJ P,MSG PUSHJ P,CRLF PUSHJ P,PNTST3 ; Now print SAT block itself ADD P3,UNIWPS(U) AOJA P1,PNTST1 PNTST2: MOVE N,P2 ; Set N=answer POPJ P, ; Return. PNTST3: JSP M,SAVE3 ; Otherwise BLKPNT destroys all.. MOVE P2,UNIWPS(U) ; # of words to print MOVE P1,P3 ; Make P1=AOBJN ptr to data PJRST BLKPN1 ; Print block and return SUBTTL SCRATCH AREA ROUTINES ;ROUTINE TO INIT THE SCRATCH DEVICE. ;CALL OUTDEV=DEVICE NAME AUXINI: MOVEI T,14 MOVE T1,AUXDEV MOVE T2,[AUXOB,,AUXIB] OPEN AUX,T POPJ P, MOVEI T2,T DEVSIZ T2, ;FIND OUT HOW BIG ITS BUFFERS ARE MOVEI T2,205 ;ASSUME 205 WORDS (DISK) HRRZM T2,AUXSIZ ;AND REMEMBER THIS FOR ALLOCATION. MOVE T,AUXDEV DEVCHR T, ;GET DEVCHR WORD FOR THIS DEVICE MOVEM T,AUXCHR ;AND REMEMBER IT TOO. JRST CPOPJ1 ;AND EXIT+1 ;SUBROUTINE TO WRITE AN END OF FILE ON AUX DEVICE AUXEOF: PUSHJ P,ZROBUF MOVSI T,'EOF' MOVEM T,BUF+EOFNAM MOVI CODEOF,BUF+EOFCOD MOVE P1,IOW PUSHJ P,AUXOUT ;WRITE EOF BLOCK TO DEVICE JFCL JFCL CLOSE AUX, MTWAT. AUX, ;WAIT FOR ALL TO FINISH MTEOF. AUX, ;WRITE AN EXTRA EOF POPJ P, ;SUBROUTINE TO RELEASE THE SCRATCH DEVICE AUXRLS: MTREW. AUX, ;REWIND IF A TAPE. POPJ P, ;SUBROUTINE TO DO 'ENTER' OR 'LOOKUP' ON SRCATCH DEVICE ;CALL OUTDEV=DEVICE ; AUXNAM,AUXEXT,AUXPPN=NAME.EXT[PPN] ; ;RET+0 ERROR ;RET+1 AOK AUXLUK: TXZA F,F.IO ;0 IF READING, AUXENT: TXO F,F.IO ;1 IF WRITING MTREW. AUX, MOVE T,AUXNAM HLLZ T1,AUXEXT SETZ T2, MOVE T3,AUXPPN MOVE M,[LOOKUP AUX,T] TXZE F,F.IO MOVE M,[ENTER AUX,T] XCT M POPJ P, JRST CPOPJ1 ;AT LAST! ;SUBROUTINE TO ALLOCATE BUFFERS FOR AUX DEVICE. ;TRYS FOR 15 BUFFERS (ABOUT 2K), WILL SETTLE FOR LESS. ;IF CONTENTS OF AUXTRY NON-ZERO, WILL TRY FOR THAT MANY INSTEAD. ;SET AUXTRY TO INFINITY TO GRAB ALL OF AVAILABLE CORE... ; ;CALL WITH F.IO SET TO WRITE, ZERO TO READ AUXALC: JSP M,SAVE3 ;SAVE SOME DATA SKIPN P1,AUXTRY ;WANT A PARTICULAR AMOUNT? MOVEI P1,^D15 ;NO. TRY FOR 15 MOVE P2,.JBMAX SUB P2,.JBFF IDIV P2,AUXSIZ ;P2=# OF BUFFERS AVAILABLE CAILE P1,(P2) ;WANT MOREN WE GOT? MOVEI P1,(P2) ;YES. SETTLE FOR ALL WE GOT. OINSTN==OUTBUF AUX,0(P1) IINSTN==INBUF AUX,0(P1) OINSTN==OINSTN_<-^D18> IINSTN==IINSTN_<-^D18> MOVSI P2,OINSTN ;MACRO WONT TAKE IT DIRECTLY.. TXNN F,F.IO MOVSI P2,IINSTN MOVE P3,.JBREL XCT P2 ;DO INBUF OR OUTBUF UUO CAME P3,.JBREL ;INCREASE CORE? PUSHJ P,PNTCOR ;YES. INFORM HIM. POPJ P, ;********* EXIT ******* ;SUBROUTINE TO OUTPUT OR INPUT FROM SCRATCH AREA ;CALL P1= IOWD TO DATA ; ; ;RET+0 HARDWARE EOF OR HORRIBLE ERROR ;RET+1 SOFTWARE EOF (THIS IS THE EOF WE LOOK FOR) ;RET+2 AOK. DATA TRANSFERRED. ; AUXIN: TXZA F,F.IO AUXOUT: TXO F,F.IO JSP M,SAVE3 HRRI P1,1(P1) ;CHANGE IOWD TO AOBJN PTR MOVE P3,P1 MOVEI P2,W.AUX TXNN F,F.IO MOVEI P2,R.AUX ;P2=ADDRESS OF BINARY OUTPUT SUBROUTINE MOVE CH,(P1) ;GET A WORD PUSHJ P,@P2 ;GO OUTPUT IT POPJ P, ;YIKES!!!!!!!!!! BETTER NOT HAPPEN! MOVEM CH,(P1) ;IN CASE READING AOBJN P1,.-4 ;AND LOOP FOR ALL WORDS. AOS (P) ;SET FOR SKIP RETURN NOW AT LEAST TXNE F,F.IO JRST CPOPJ1 ;ALL IS WELL IF WRITING MOVEI P1,CODEOF CAME P1,EOFCOD(P3) ;THIS AN EOF BLOCK?? JRST CPOPJ1 ;NO. DATA MOVSI P1,'EOF' CAME P1,EOFNAM(P3) JRST CPOPJ1 POPJ P, ;YES. GIVE SOFT EOF RETURN. ;SUBROUTINE TO WRITE ONE WORD TO THE AUX DEVICE. ;CALL CH=WORD ;RET+0 HORRIBLE ERROR ;RET+1 AOK. W.AUX: JSP M,SAVE3 MOVI ^D10,AUXTRY ;RETRY UP TO 10 TIMES ON ERRORS W.AUXX: SOSLE AUXOB+2 JRST W.AUX1 OUT AUX, JRST W.AUX1 GETSTS AUX,P1 SETSTS AUX,14 TXNN P1,IO.BKT!IO.EOF!IO.EOT JRST W.AUX2 MOVE P2,AUXCHR ;SEE WHAT WERE WRITING ON TXNN P2,DV.MTA ;A MAG TAPE? JRST W.AUX4 ;NO. SKIP THIS STUFF MTEOF. AUX, ;AT EOT, WRITE TWO EOF MARKS MTWAT. AUX, ;SO THAT WE WILL BE ABLE TO READ MTEOF. AUX, ;THIS TAPE BACK WITHOUT GOING MTWAT. AUX, ;OFF THE END OF THE REEL! MTUNL. AUX, ;OF COURSE, IF NOT A TAPE, IGNORE THIS.. W.AUX4: MOVEI M,EOFMSG W.AUX0: PUSHJ P,OPER JRST DIE005 JRST W.AUXX W.AUX1: IDPB CH,AUXOB+1 JRST CPOPJ1 ;SUCESFULL ******** EXIT ********** W.AUX2: TXNN P1,IO.IMP ;TAPE WRITE-LOCK ERROR? JRST W.AUX3 ;NO. WORSE YET. MOVEI M,[ASCIZ/ %AUX unit write-locked. Please fix and proceed./] JRST W.AUX0 W.AUX3: SOSLE AUXTRY ;TRY UP TO 10 TIMES JRST W.AUXX MOVEI M,ERRMSG ;THEN GIVE UP AND TELL HIM WE DID. PJRST MSGTTY R.AUX: JSP M,SAVE3 R.AUXX: SOSLE AUXIB+2 JRST R.AUX1 IN AUX, JRST R.AUX1 GETSTS AUX,P1 SETSTS AUX,14 TXNN P1,IO.EOF!IO.BKT!IO.EOT ;DONE? JRST R.AUX2 MOVEI M,EOFMSG MTUNL. AUX, PUSHJ P,OPER JRST DIE005 JRST R.AUXX R.AUX1: ILDB CH,AUXIB+1 JRST CPOPJ1 R.AUX2: MOVEI M,ERRMSG PJRST MSGTTY EOFMSG: ASCIZ/ %EOF on AUX unit. Please mount another/ ERRMSG: ASCIZ/ %AUX unit data error/ SUBTTL Register save routines ; Here to save AC's P1,P2,T,T1 ; Call with JSP M,BUFSAV BUFSAV: MOVEM CH,SAVECH PUSH P,T1 PUSH P,T PUSH P,P1 PUSH P,P2 PUSHJ P,(M) SKIPA AOS -4(P) POP P,P2 POP P,P1 POP P,T POP P,T1 POPJ P, ; Here to save P1 & P2 & P3 ; Call with JSP M,SAVE3 SAVE3: PUSH P,P1 PUSH P,P2 PUSH P,P3 PUSHJ P,(M) JRST .+5 ; POPJ return AOSA -3(P) ; CPOPJ1 return AOSA -3(P) ; CPOPJ2 return SKIPA AOS -3(P) POP P,P3 POP P,P2 POP P,P1 POPJ P, ; Here to save all AC's. Watch pushdown level! ; Call with PUSHJ P,SAVALL (P not saved) SAVALL: MOVEM 16,17(P) MOVEI 16,1(P) BLT 16,16(P) MOVE 16,17(P) ADD P,[17,,17] PUSHJ P,@-17(P) SKIPA AOS -20(P) MOVSI 16,-16(P) BLT 16,16 SUB P,[20,,20] POPJ P, SUBTTL Information printing routines ; Subroutine to calculate the CFP given a block in the structure. ; Call with N = Block in STR, ; U = UDB address CFPPFX: MOVEI M,[ASCIZ/, CFP /] PUSHJ P,MSGTTY ; Print prefix IDIV N,HOMBSC(U) ; Convert to supercluster number PJRST OCTPRT ; Print it and return ; ; ; Subroutine to print the first and last block in a cluster ; Call with N = first block in cluster CLSBLK: MOVEI M,[ASCIZ/Blocks /] PUSHJ P,MSGTTY ; Put out prefix PUSH P,N ; Save block number PUSHJ P,OCTPRT ; Print first block MOVEI M,[ASCIZ/ through /] PUSHJ P,MSGTTY ; Print separator POP P,N ; Restore first block ADD N,STRBPC ; Compute last block+1 SUBI N,1 ; Make it last block PJRST OCTPRT ; Print it and return ; ; ; Subroutine to print a block/cluster number ; Call with N = number to print BLKPFX: SKIPA M,[[ASCIZ/Block /]] CLSPFX: MOVEI M,[ASCIZ/Cluster /] PUSHJ P,MSGTTY ; Put out correct prefix PJRST OCTPRT ; Print number and return ; ; ; Subroutine to print relative block/Number in BARG1 ; Call RLBPFX with N = relative block, ; PREFIX with M = message address, number to print in N RLBPFX: SKIPA M,[[ASCIZ/, Relative block /]] PREFIX: MOVE N,BARG1 ; Load number for PREFIX call PUSHJ P,MSGTTY ; Print the message PJRST OCTPRT ; Print the number and return ; ; ; Subroutine to print a unit number ; Call with N = unit number UNIPFX: MOVEI M,[ASCIZ/ Unit /] PUSHJ P,MSGTTY ; Print prefix PUSHJ P,OCTPRT ; Print the unit number PUSHJ P,COLON ; Add a colon PJRST TAB ; End with a tab and return ; ; ; Subroutine to print a prefix for the /C code STRPFX: PJSP M,MSGTTY ; Print message and return ASCIZ/ Structure: / ; Subroutine to compute and print physical disk address of ; logical block in AC 'T2' PBNPRT: MOVEI M,[ASCIZ .Cylinder .] PUSHJ P,MSG IDIV T2,BLKCYL(U) ; T2=Cyl, T3=remainder MOVE N,T2 PUSHJ P,OCTPRT ; Print CYL in octal MOVEI M,[ASCIZ \ surface \] PUSHJ P,MSG MOVE T2,T3 IDIV T2,BLKTRC(U) ; T2=Surface, T3=Sector(track) MOVE N,T2 PUSHJ P,OCTPRT ; MOVEI M,[ASCIZ \ sector \] PUSHJ P,MSG MOVE N,T3 PJRST OCTPRT ; ; Subroutine to print file information for the /F code. The line ; produced is of the form: ; ; DSKB0 (RPA1) FOO BAZ [10,7] Block in unit = nnn, Block in str = nnn ; ; Call with T = block in str, ; T1 = block in unit PRTFND: PUSH P,T ; Save T and T1 for later PUSH P,T1 MOVE M,HOMLOG(U) ; Get logical unit name PUSHJ P,PR6BIT ; and print it MOVEI M,[ASCIZ/ (/] ; PUSHJ P,MSG ; MOVE M,DRIVE(U) ; Get drive it's on PUSHJ P,PR6BIT ; and print it MOVEI M,[ASCIZ/) /] ; PUSHJ P,MSG ; TXO F,F.NOTB ; Use dot instead of tab PUSHJ P,FILPNT ; Print the file and ext PUSHJ P,SPC ; PUSHJ P,UFDPNT ; and the path MOVEI M,[ASCIZ/ Block in unit = /] PUSHJ P,MSG ; POP P,N ; Get back value PUSHJ P,OCTPRT ; and print it MOVEI M,[ASCIZ/, Block in str = /] PUSHJ P,MSG ; POP P,N ; PUSHJ P,OCTPRT ; PJRST CRLF ; End with CRLF and return ; Routine to tell the user that we found a match in the /WS code. ; The line produced is of the form: ; ; RPA0 (DSKB0) Block = n, Relative word = n, Matched word = n ; ; Call with T = AOBJN ponter to relative word in BUF, ; U = UDB address of unit PRTMAT: PUSH P,T ; Save the pointer AOSE PASS ; Been here before? JRST PRTMT1 ; Yes, skip the header PUSHJ P,SWWPRT ; Type values of mask and search word PUSHJ P,CRLF2 ; and a couple of CRLFs PRTMT1: MOVE M,DRIVE(U) ; Get physical unit name PUSHJ P,PR6BIT ; and print it in SIXBIT MOVEI M,[ASCIZ/ (/] PUSHJ P,MSG ; Separate fields MOVE M,HOMLOG(U) ; Get logical name PUSHJ P,PR6BIT ; and print it in SIXBIT too MOVEI M,[ASCIZ/) Block = /] PUSHJ P,MSG ; Header for next field MOVE N,CURPOS(U) ; Get current block number PUSHJ P,OCTPRT ; and print it in octal MOVEI M,[ASCIZ/, Relative word = /] PUSHJ P,MSG ; Another header HRRZ N,(P) ; Get relative word in block PUSHJ P,OCTPRT ; and print it in octal MOVEI M,[ASCIZ/, Matched word = /] PUSHJ P,MSG ; Final header HRRZ N,(P) ; Get relative word in block again MOVE N,BUF(N) ; Get word that we matched PUSHJ P,OCTL12 ; and print it in octal POP P,T ; Restore T PJRST CRLF ; Print final CRLF and return ; Routine to search the block in BUF for a match with a specified ; word. ; ; Call with WMASK = search mask to use, ; WWORD = search word to find WRDMAT: MOVSI T,-BLKSIZ ; Make AOBJN pointer WRDMT1: MOVE T1,BUF(T) ; Get next word in BUF XOR T1,WWORD ; Exclusive OR with search word AND T1,WMASK ; Mask only those interesting bits JUMPN T1,.+2 ; No match if word non-zero PUSHJ P,PRTMAT ; Tell user of match AOBJN T,WRDMT1 ; Loop for all words POPJ P, ; and return ; ; ; Routine to type the contents of the search mask and word. ; Call with TTY output enabled if desired. SWWPRT: MOVEI M,[ASCIZ/ Mask word = /] PUSHJ P,MSG ; Type explanation MOVE N,WMASK ; Get the mask word PUSHJ P,OCTL12 ; Type as 12 digits of octal MOVEI M,[ASCIZ/, Search word = /] PUSHJ P,MSG ; One more label MOVE N,WWORD ; Get search word PUSHJ P,OCTL12 ; Type this as 12 digits octal also PJRST CRLF ; End with CRLF and return SUBTTL Disk list routines ; Here to process most /P switches. Most of this code was ; slightly lifted from DSKLST originally... ; At first I wanted to simulate DSKLST output exactly. Since ; then I have changed the output format a bit. DSKLST: TTYOFF TXNN SW, TXO SW, SKIPN BARG3 ; BARG3 TXNE SW,CH.L ; or /PL SKIPA ; implies F and not all else.. JRST ANOTHR TXO SW,CH.F ; L implies F and not all else TXZ SW, ANOTHR: PUSHJ P,NXTSTR ; Initialize first STR JRST RIPDON JFCL TXNE SW,CH.L JRST NOKEY ; Skip all this for /L SETZM TBLKCT ; Clear total blocks used on STR SETZM NULUFD ; Count of null UFD's SETZM UFDCNT ; Total blocks used in UFD's SETZM WASTEB ; Wasted blocks due to cluster allocation SETZM TFILCT ; Total number of files SETOM TEMP3 ; Set flag for first time through on STR TXNN SW,CH.U!CH.V ; Doing /PU or /PV? JRST NOCLS ; Skip units if not wanted MOVEI U,UNIDDB NXTU: HLRZ U,(U) ; Next unit JUMPE U,NOCLS ; Until done TXNN SW,CH.V ; Doing /PV? AOSG TEMP3 ; or not first time on /PU? SKIPA ; Yes to one, print header JRST NXTU1 PUSHJ P,CRLF2 MOVEI M,UHED PUSHJ P,MSG NXTU1: MOVE M,DRIVE(U) PUSHJ P,PR6BIT ; Physical device PUSHJ P,TAB MOVE M,HOMHID(U) PUSHJ P,PR6BIT ; System id PUSHJ P,TAB MOVE M,HOMLOG(U) PUSHJ P,PR6BIT ; Log. unit in STR PUSHJ P,CRLF ; End line with CRLF TXNN SW,CH.V ; Doing /PV? JRST NXTU ; No, skip rest of stuff PUSHJ P,PNTHOM ; Print home block HRLZI T,UNITAB HRRI T,HOMHID(U) PUSHJ P,LSTPNT ; Print the entire UDB PUSHJ P,FORM ; Eject the page JRST NXTU ; and repeat for all units NOCLS: TXNN SW,CH.F JRST NOHEAD MOVEI M,[ASCIZ/ Key for error bits: Bit Meaning /] PUSHJ P,MSG ; Print key for error bits HRLZI P1,-KEYLEN PNTKEY: PUSHJ P,TAB HLRZ N,KEYS(P1) PUSHJ P,OCTPRT PUSHJ P,TAB HRRZ M,KEYS(P1) PUSHJ P,MSG PUSHJ P,CRLF AOBJN P1,PNTKEY PUSHJ P,CRLF2 JRST NOKEY DEFINE KEYMAC (X,Y) < XWD X , [ASCIZ/Y/] > KEYS: KEYMAC RIPBDA ,Error found by damage assessment program KEYMAC RIPCRH ,Partially written file closed after monitor stop KEYMAC RIPBFA ,Error found by BACKUP KEYMAC RIPHRE ,Hardware data read error KEYMAC RIPHWE ,Hardware data write error KEYMAC RIPSCE ,Software checksum or redundancy error KEYLEN== .-KEYS NOKEY: MOVEI M,HED1 ; Print DSKLST header PUSHJ P,MSG NOHEAD: MOVE T,[TBLKCT,,TBLKCT+1] BLT T,HISTO+TOPHIS+1 ; Clear all counters TXNN SW,CH.F!CH.E!CH.P ; Do files if F or E or P JRST DSAT MOVE T,[HISTOR,,HISTOR+1] SETZM HISTOR BLT T,HISTOR+TOPHIS RML: PUSHJ P,NXTDIR ; Get next directory JRST FINIS TXZ F,F.NULL ; Assume non-null UFD PUSHJ P,NXTFIL ; Any files for this user? TXOA F,F.NULL ; no. Remember this JRST RML1 ; Yes. Go process SETCM T,F ; No. We want a ufdmsg only if: TXNN T,S.NAM!S.EXT ; Both name and ext were stars, TXNE SW,CH.L ; and /L not in progress JRST RML ; Otherwize, ignore null UFD's AOS NULUFD ; Count number of them... RML1: TXNN SW,CH.F JRST RML2 ; Not printing files - still must allocate PUSHJ P,CRLF2 ; To make it look good MOVE M,HOMSNM(U) ; Get device name PUSHJ P,PR6BIT ; Type it PUSHJ P,COLON ; of course PUSHJ P,UFDPNT ; and the path PUSHJ P,CRLF2 RML2: SETZM UBLKCT SETZM UFILCT TXZE F,F.NULL ; Was this a null UFD? JRST DONEU ; Yes. Dont attempt to read files JRST RUL1 RUL: PUSHJ P,NXTFIL ; Get next user file name JRST DONEU RUL1: PUSHJ P,USRLOK ; LOOKUP this file JRST RUL ; No good. Ignore it PUSHJ P,CNTBLK ; Go count blocks allocated TXNE SW,CH.L JRST RUL3 MOVE T,BUF+RIBSTS TXNN T,RIPHRE!RIPHWE!RIPSCE!RIPBDA!RIPBFA!RIPCRH JRST RUL3 ; No errors. Why check? TXNE T,RIPHWE AOS FERR ; File has had hard write error TXNE T,RIPHRE AOS FERR+1 ; File has had hard read error TXNE T,RIPSCE AOS FERR+2 ; File has had software checksum error TXNE T,RIPBDA AOS FERR+3 ; File found bad by damage assement program TXNE T,RIPBFA AOS FERR+4 ; File found bad by BACKUP TXNE T,RIPCRH AOS FERR+5 ; File closed after a crash RUL3: AOS UFILCT ; Count user files TXNN SW,CH.F JRST RULA SKIPN N,BARG3 ; File size specified? JRST RUL3A ; No CAML N,BUF+RIBALC ; Smaller than allocated blocks for this file? JRST RUL ; No, ignore it RUL3A: PUSHJ P,FILPNT MOVE N,DSK+RIBLBN ; Give block number of 1st rib MOVEI T,7 PUSHJ P,OCTSPC PUSHJ P,SPC2 PUSHJ P,DIRLST ; Print file attributes RULA: MOVE T,BUF+RIBSIZ ; Words written ADDI T,BLKSIZ-1 LSH T,-7 ; Convert to blocks written TXNN SW,CH.P ; Doing histogram JRST RULA1 ; Nope CAILE T,TOPHIS+1 ; Skip if within histogram MOVEI T,TOPHIS+1 ; Note off top AOS HISTO(T) ; Count # of files of this length RULA1: MOVEI P4,DSK PUSHJ P,PTRCPY ; Copy ptrs into UDB so can count them SETZM TEMP2 ; TEMP2 = count of real ptrs SETOM TEMP3 ; TEMP3 = flag, set zero if extra RIB RUL1C: PUSHJ P,GETPTR ; Get a ptr JUMPE P1,RUL1B ; Quit if done AOS TEMP2 ; Inc count TXNE F,F.NEWR ; RIB extended? SETZM TEMP3 ; Yes. flag it JRST RUL1C ; and loop RUL1B: MOVE N,TEMP2 TXNN SW,CH.P ; Doing histogram? JRST RULB ; Nope CAILE N,TOPHIS+1 MOVEI N,TOPHIS+1 AOS HISTOR(N) ; Historgram # of RIB ptrs RULB: TXNN SW,CH.F JRST RUL MOVE N,BUF+RIBSIZ MOVEI T,6 PUSHJ P,DECSPC ; Print words written PUSHJ P,SPC MOVE N,BUF+RIBALC ; Blocks allocated MOVEI T,7 PUSHJ P,DECSPC LDB N,EXLERB ; Get error bits MOVEI T,5 PUSHJ P,OCTSPC PUSHJ P,TAB MOVE N,TEMP2 MOVEI T,5 PUSHJ P,DECSPC ; Print number of real pointers MOVEI CH," " SKIPN TEMP3 MOVEI CH,"*" PUSHJ P,W.LST ; Print * if extended PUSHJ P,CRLF JRST RUL ; and loop for more files ; Subroutine to list file attributes. ; Prints access data, creation time,date, protection code, and mode DIRLST: PUSHJ P,FILACD ; Get T3=date last accessed PUSHJ P,PRDATE ; and print it PUSHJ P,FILDAT ; Get universal date,,time PUSH P,T3 ; and save it for a while PUSHJ P,PRTIM1 ; Print as hh:mm POP P,T3 ; Get back creation date,,time PUSHJ P,PRDATE ; Print the date. LDB N,EXLPRV ; Access privileges MOVEI T,3 PUSHJ P,OCTZRO LDB N,EXLMOD ; Mode MOVEI T,3 PUSHJ P,OCTSPC PJRST SPC2 ; Here to total user's allocated blocks and words, ; and count blocks and words wasted CNTBLK: MOVE T,BUF+RIBALC ; Blocks allocated for file ADDM T,UBLKCT ; Count users blocks MOVE T1,BUF+RIBSIZ ; Words written ADDI T1,BLKSIZ-1 IDIVI T1,BLKSIZ ; T1=blocks written SUB T,T1 ; T=blocks alloc. but not written SUBI T,2 ; -2 for RIBs ADDM T,WASTEB ; Gives # of wasted blocks POPJ P, ; Subroutine to print K for swapping on unit ; Called from LSTPNT with N=words K4SPNT: PUSH P,N PUSHJ P,DECPR1 MOVEI M,[ASCIZ/K = /] PUSHJ P,MSG POP P,N LSH N,3 ; Blocks = K * 8 PUSHJ P,DECPRT MOVEI M,[ASCIZ/ blocks/] PJRST MSG DONEU: MOVE T,USRPTH+.PTPPN MOVE N,UFILCT ; Number of user files CAMN T,MFDPPN MOVEM N,MFDCT ; Count number of UFDs ADDM N,TFILCT ; Total number of files MOVE N,UBLKCT ; Add user's blocks to total for str CAMN T,MFDPPN ; If this is the MFD, MOVEM N,UFDCNT ; Remember total blocks devoted to UFDs. ADDM N,TBLKCT TXNN SW,CH.F JRST RML ; If not printing files, on to next user DONEU1: PUSHJ P,CRLF PUSHJ P,TAB PUSHJ P,DECPRT ; Print number of blocks allocated MOVEI M,BLKMSG PUSHJ P,MSG MOVEI M,UBLKMG PUSHJ P,MSG MOVEI M,AVEMSG ; Now get average file size PUSHJ P,MSG MOVE N,UFILCT PUSHJ P,DECPRT MOVEI M,AVEMS1 PUSHJ P,MSG MOVE N,UBLKCT ; Blocks allocated IDIV N,UFILCT ; Compute average file size PUSHJ P,DECPRT ; and print MOVEI M,UBLK1 PUSHJ P,MSG JRST RML FINIS: TXNN SW,CH.F ; If not printing files, move on JRST DSAT PUSHJ P,CRLF3 PUSHJ P,TAB MOVE N,TBLKCT ; Total number of blocks allocated on STR PUSHJ P,DECPRT MOVEI M,BLKMSG PUSHJ P,MSG MOVEI M,TBLKMG PUSHJ P,MSG MOVEI M,AVEMSG ; Now get average file size PUSHJ P,MSG MOVE N,TFILCT ; Number of files PUSHJ P,DECPRT ; and print MOVEI M,AVEMS1 PUSHJ P,MSG MOVE N,TBLKCT IDIV N,TFILCT ; Compute average file size PUSHJ P,DECPRT MOVEI M,UBLK1 PUSHJ P,MSG TXNE SW,CH.L JRST NOPERF ; Here to compute & print SAT blocks DSAT: MOV .JBFF,.SVFF ; Save so we can restore core PUSHJ P,RDSAT ; Read disk SATS JRST DSAT3 SETZM TOTSAT ; clear tally of free blocks MOV USRSTR,BUF ; Set BUF=STR name MOVE T,[.DCFCT+1,,BUF] DSKCHR T, ; Ask monitor what it thinks. SETZM BUF+.DCFCT ; It doesnt. MOV BUF+.DCFCT,TOTDSK ; Remember what monitor thought free was. MOVEI U,UNIDDB DSAT1: HLRZ U,(U) JUMPE U,DSAT2 TXNE SW,CH.S PUSHJ P,PNTSAT ; Print SAT if he wants it TXNN SW,CH.S PUSHJ P,CNTSAT ; But must at least count zbits ADDM N,TOTSAT ; Tally free blocks JRST DSAT1 ; Loop for all units DSAT2: TXNN SW,CH.S JRST DSAT3 PUSHJ P,CRLF2 MOVE N,TOTSAT PUSHJ P,DECPRT ; Print total blocks free on str MOVEI M,BLKMSG PUSHJ P,MSG MOVEI M,TOTMSG PUSHJ P,MSG DSAT3: PUSHJ P,ZCORE ; Return core TXNN SW,CH.B ; Skip if BAT blocks wanted JRST ESUM ; No, move on ; Here to compute & print BAT blocks.. MOVEI U,UNIDDB BATB: HLRZ U,(U) ; Get next logical unit in STR JUMPE U,ESUM ; Until done. PUSHJ P,FORM ; Eject page for neatness MOVEI M,BATHED PUSHJ P,MSG MOVE M,HOMLOG(U) ; M=Unit ID PUSHJ P,PR6BIT ; Print log unit MOVEI CH,"(" PUSHJ P,W.LST MOVE M,HOMHID(U) PUSHJ P,PR6BIT ; Print unit ID MOVEI M,[ASCIZ .) Currently on .] PUSHJ P,MSG MOVE M,DRIVE(U) PUSHJ P,PR6BIT PUSHJ P,CRLF PUSHJ P,BATCHK ; Read BAT block JRST BATB SETZM OTHERK MOVEI M,[ASCIZ / Number bad blocks (MAP) = /] PUSHJ P,MSG LDB N,BAYNBS ; Get number of bad sectors PUSHJ P,DECPRT MOVEI M,[ASCIZ / Number bad regions (MAP) = /] PUSHJ P,MSG LDB N,BAYNBR ; Bad regions found by MAP program PUSHJ P,DECPRT MOVEI M,[ASCIZ / Number bad regions (MON) = /] PUSHJ P,MSG HRRZ N,BUF+BAFCNT ; Bad regions found by monitor PUSHJ P,DECPRT MOVEI M,[ASCIZ \ Controller device code (MAP) = \] PUSHJ P,MSG LDB N,BAYKDC LSH N,2 PUSHJ P,OCTPRT PUSHJ P,BLKPRT ; Now zap out the whole block HRRZ P2,BUF+BAFFIR ; Get relative offset of 1st pair HLRE T,BUF+BAFFIR ; Get -number free words MOVNS T ; Make it positive ADDI P2,BUF-1(T) ; Point to last word pair HRLI P2,-2(T) ; Move count to LH BATB3: SKIPE -1(P2) ; Skip if this pair unused JRST BATB4 ; Start processing loop SUB P2,[2,,2] ; Decrement count and pointer JUMPL P2,BATB ; Done when count < 0 JRST BATB3 ; Else just loop BATB4: MOVEI M,[ASCIZ .Bad regions listed most recently found first: .] PUSHJ P,MSG BATB5: LDB T2,BAYELB ; Get first block in region (new entry) MOVX M,BAPNTP ; Get new entry bit TDNN M,-1(P2) ; Is this a new type entry? HRRZ T2,(P2) ; No, only RH is block adr PUSH P,T2 ; Save it for later PUSHJ P,PBNPRT ; Print physical disk address MOVEI M,[ASCIZ \ = block \] PUSHJ P,MSG MOVE N,(P) ; Get block number back PUSHJ P,OCTPRT ; LDB T2,BAYNBB ; # bad blocks this region JUMPE T2,ONLY1 ; Jump if only 1 block MOVEI M,[ASCIZ . through .] PUSHJ P,MSG MOVE T3,(P) ; T3 is block no. of first bad block ADD T2,T3 ; T2=last block # PUSHJ P,PBNPRT MOVEI M,[ASCIZ \ = \] PUSHJ P,MSG LDB T2,BAYNBB ; Get number of bad blocks MOVEI N,1(T2) ; and tell him PUSHJ P,DECPRT MOVEI M,[ASCIZ \ Bad blocks\] PUSHJ P,MSG ONLY1: POP P,(P) ; Discard block adr MOVEI M,[ASCIZ . Found on .] PUSHJ P,MSG MOVX M,BAPOTH TDNN M,-1(P2) ; Skip if found on another kontroller JRST ONLY1F ; No MOVEI CH,"*" PUSHJ P,W.LST SETOM OTHERK ONLY1F: HLLZ M,DRIVE(U) ; Device name TLZ M,77 ; Make it controller type (DP, RP, etc.) PUSHJ P,PR6BIT LDB CH,BAYKNM ; Get logical controller number ADDI CH,"A" ; Make it ASCII PUSHJ P,W.LST MOVEI M,[ASCIZ . unit(s) .] PUSHJ P,MSG SETO P1, ; P1=unit number LDB T2,BAYPUB ; T2=bits 10-17 of BAF word ; Bit 17-N=unit number MOVEI T3,1 ; Start looking at bit 35(unit 0) TXOA F,F.TMP ; Set bit for first time through BADU1: LSH T3,1 ; Try the next bit AOS N,P1 ; Which means next unit. JUMPE T2,BADU2 ; Done if no more bits set TRZN T2,(T3) ; Look at this bit, zero it if set JRST BADU1 ; Not set, try next bits TXZN F,F.TMP ; Skip if this is the first time PUSHJ P,COMMA ; cause first unit doesn't get comma PUSHJ P,OCTPRT ; Print unit number JRST BADU1 ; and loop for more units BADU2: MOVEI M,[ASCIZ/ Processor /] PUSHJ P,MSG LDB N,BAYAPN ; Serial number of arithmetic processor PUSHJ P,DECPR1 MOVX M,BAPNTP ; Get new type entry bit TDNN M,-1(P2) ; Is this a new type entry? JRST BATB6 ; No, do it the old way MOVEI M,[ASCIZ\. Error bits = \] PUSHJ P,MSG ; Start of message LDB N,BAYERR ; Get the error bits PUSHJ P,OCTPRT ; and print in octal JRST BATB7 ; Skip the old style stuff BATB6: MOVEI M,[ASCIZ \. Bits 12-29 of CONI = \] PUSHJ P,MSG HLRZ N,(P2) ; Get CONI bits MOVEI T,6 PUSHJ P,OCTZRO ; Print as 6 octal digits BATB7: PUSHJ P,CRLF2 ; End entry with 2 CRLF's SUB P2,[2,,2] ; Decrement counter and pointer JUMPGE P2,BATB5 ; Loop if not done MOVEI M,[ASCIZ \ * Also found on some other controller of processor \] SKIPE OTHERK ; Skip if no regions found bad on another kontroller PUSHJ P,MSG JRST BATB ESUM: TXNN SW,CH.E JRST NOSUM ; Don't want error summary MOVEI M,[ASCIZ/ Error summary for /] PUSHJ P,MSG MOVE M,USRSTR PUSHJ P,PR6BIT MOVEI M,WASMSG ; 'blocks wasted in unwritten but allocated blocks PUSHJ P,MSG MOVE N,WASTEB PUSHJ P,DECPRT PUSHJ P,SLASH MOVE N,TBLKCT ; Get total # of blocks written PUSHJ P,DECPRT PUSHJ P,EQUAL MOVE N,WASTEB IMULI N,^D100 ; Now express as a percentage IDIV N,TBLKCT PUSHJ P,DECPRT PUSHJ P,%CRLF MOVEI M,MSGRIB ; 'number of blocks used for ribs =' PUSHJ P,MSG MOVE N,TFILCT LSH N,1 MOVE U,N PUSHJ P,DECPRT MOVEI M,[ASCIZ/ Plus /] PUSHJ P,MSG MOVE N,UFDCNT ; 'plus xxx blocks in ufds' PUSHJ P,DECPRT MOVEI M,[ASCIZ/ blocks in UFDs = /] PUSHJ P,MSG ADD U,UFDCNT SUB U,MFDCT ; Subtract blocks in MFD ribs MOVE N,U ; which are counted twice PUSHJ P,DECPRT PUSHJ P,SLASH MOVE N,TBLKCT PUSHJ P,DECPRT PUSHJ P,EQUAL MOVE N,U IMULI N,^D100 ; Again as a percentage IDIV N,TBLKCT PUSHJ P,DECPRT MOVEI M,[ASCIZ/% system overhead for retrieval information/] PUSHJ P,MSG MOVEI M,NULMSG ; 'number of null ufds =' PUSHJ P,MSG MOVE N,NULUFD PUSHJ P,DECPRT PUSHJ P,CRLF2 SETCM T,F TXNE T,STNDRD JRST ALLMAT ; Not doing all files, dont print discrepancies. MOVE N,STRSIZ ; Total blocks on STR SUB N,TBLKCT ; Computed free = total - used CAMN N,TOTSAT ; Compare with SAT 0 bits JRST ALLMAT ; If no discrepancy, dont print MOVEI M,MISMSG PUSHJ P,MSG PUSHJ P,DECPRT ; Print computed free blocks PUSHJ P,TAB2 MOVE N,TOTSAT ; Print computed from SAT PUSHJ P,DECPRT PUSHJ P,TAB2 MOVE N,TOTDSK ; Computed from DSKCHR by monitor PUSHJ P,DECPRT PUSHJ P,CRLF ALLMAT: MOVEI M,ERRHED PUSHJ P,MSG HRLZI P1,-6 MOVE N,FERR(P1) ; Print each file error counter PUSHJ P,DECPRT PUSHJ P,TAB AOBJN P1,.-3 PUSHJ P,CRLF NOSUM: TXNN SW,CH.P ; Skip if performance statistics desired JRST NOPERF PUSHJ P,FORM MOVEI M,HISHED ; Histogram header PUSHJ P,MSG SETZ T, ; start at beginning HISLOP: PUSHJ P,HISLIN ; Print length of file & number of files CAIE T,TOPHIS ; See if reached top AOJA T,HISLOP ; No, keep going MOVEI M,[ASCIZ .GE .] PUSHJ P,MSG ADDI T,1 PUSHJ P,HISLIN NOPERF: PUSHJ P,FORM JRST ANOTHR ; and continue HISLIN: MOVE N,T ; Number of blocks written PUSHJ P,DECPR1 PUSHJ P,TAB2 MOVE N,HISTO(T) ; Number of files of that length PUSHJ P,DECPR1 PUSHJ P,TAB2 MOVE N,HISTOR(T) ; Number of RIBs of that length PUSHJ P,DECPR1 PJRST CRLF ; Here on /P followed by A,O,7,6,R,D or Q ; Print data in file or blocks in ASCII, octal, SIXBIT, RIB, ; directory, or quick format ; ; /PA lists file or blocks like type command ; /PO dumps in octal ; /P7 dumps file is ASCII with block header ; /P6 dumps file in SIXBIT ; /PR prints the RIB of the file specified, or the block specified if ; it is a RIB ; /PD prints the block of file like it was a UFD ; /PQ is like a DIR/F DATLST: PUSH P,BARG1 ; Save all block args PUSH P,BARG2 PUSH P,BARG3 DATL0: PUSHJ P,NXTSTR ; Get next STR JRST DATL3 ; When done JFCL ; Don't care about MFD DATL1: SKIPE GOTWRD ; Numeric argument? JRST DATL5 ; Yes. List blocks, not files PUSHJ P,NXTDIR ; Get next directory JRST DATL0 DATL2: PUSHJ P,NXTFIL ; Get next file JRST DATL1 ; No more files TXNN SW,CH.Q ; No form if /PQ PUSHJ P,FORM TXNE SW,CH.R ; Printing RIBs? JRST DATL7 ; Yes. Slightly different TXO F,F.NOTB ; Use dot instead of tab PUSHJ P,FILPNT ; Print file name,ext etc.. PUSHJ P,UFDPNT ; and path TXNE SW,CH.Q ; If /PQ JRST [PUSHJ P,CRLF ; then we're done JRST DATL2] PUSHJ P,TAB PUSHJ P,USRLOK ; LOOKUP the file JRST DATL2 ; Not there.. MOV IOW,XIOWD+DSK PUSHJ P,NOW ; Print time now PUSHJ P,CRLF3 DATL4: MOVEI P4,DSK PUSHJ P,DMPIN ; Get a block MOVE T,IOSTS+DSK ; Get status TXNE T,IO.EOF ; EOF? JRST DATL2 ; Yes. Go back for more files TXNN SW,CH.A ; /PA? PUSHJ P,CRLF ; No, print crlf between blocks PUSHJ P,DATL6 ; Go to various printing routines JRST DATL4 ; and try remaining blocks ; Here to print given blocks. DATL5: MOVEI P4,DSK MOVE T1,BARG1 MOVE T,IOW PUSHJ P,STRRED ; Go read blocks JFCL ; Error, but print block anyway PUSHJ P,DATL6 ; Go print the block AOS T,BARG1 CAMGE T,BARG2 ; Done all blocks requested? JRST DATL5 ; No. Get more TXNN SW,CH.R ; Printing RIBs? JRST DATL0 ; No. Done SKIPL BARG2 ; Yes. Did he give blocks or files? JRST DATL0 ; Blocks. Done SETZM BARG1 ; Files. Get next one JRST DATL2 ; Here on /PR - Print RIBs DATL7: MOVE T,USRCFP PUSHJ P,CFP2BK ; Find block # of first RIB MOVEM T,BARG1 ; and make it look like thats what he typed SETOM BARG2 ; Set -1 as flag saying file typed, not block JRST DATL5 DATL3: POP P,BARG3 ; Restore block args POP P,BARG2 POP P,BARG1 JRST RIPDON ; and finish up ; Here to dispatch to printing... DATL6: TXNE SW,CH.R ; RIBs? PUSHJ P,RIBPNT TXNE SW,CH.D ; UFDs? PUSHJ P,DIRPRT TXNE SW,CH.O ; Octal? PUSHJ P,BLKPRT TXO F,F.CRLF TXNE SW,CH.A ; ASCII? PUSHJ P,ASCOUT ; Yes. Print it, no carriage rets. TXZ F,F.CRLF TXNE SW,CH.7 ; 7-Bit ASCII? PUSHJ P,ASCOUT ; Yes. One block at a time. TXNE SW,CH.6 ; SIXBIT? PUSHJ P,SIXOUT POPJ P, SUBTTL SORT - Shell sort routine, optimized for RIPOFF use REPEAT LOGIC,< CALL: T ADDRESS OF VECTOR N NUMBER OF ENTRIES TO SORT T1 KEY FOR SORT KEY=0, SORT 2 WORD ENTRIES ON BOTH WORDS (/AF) KEY=1, SORT 2 WORD ENTRIES ON LEFT HALF OF SECOND WORD, THEN FIRST WORD (/AE) KEY=2, SORT 3 WORD ENTRIES ON THIRD WORD (/AT) ALL AC'S PRESERVED. SORT IS IN PLACE, DOES NOT REQUIRE ANY EXTRA CORE. THE SORT ALGORITHM IS AS FOLLOWS: N=NUMBER OF ENTRIES, V=VECTOR SORT: M=N SORT1: M=M/2 IF M=0, RETURN J=1 SORT2:I=J SORT4: IF V(I) .LE. V(I+M) , GOTO SORT3 SWITCH V(I) WITH V(I+M) I=I-M IF I .GE. 1 , GOTO SORT4 SORT3: J=J+1 IF J .GT. N-M , GOTO SORT1 GOTO SORT2 GIVEN N ENTRIES TO SORT, ALGORITHM WILL COMPARE EXACTLY [LOG2(N)]*[N/2] WHERE [X] DENOTES GREATEST INTEGER FUNCTION OF X, LOG2(X) IS LOG BASE TWO. > ;DEFINE SOME AC'S FOR MY USE HERE KEY==T1 ;KEY FOR SORT TMP==KEY ;A GENERAL PURPOSE REGISTER TOO.. N==N ;N STAYS THE SAME V1==T ;ADDRESS OF VECTOR V2==T2 ;ADDRESS OF VECTOR+1 V3==T3 ;ADDRESS OF VECTOR+2 INDEX==P1 ;INDEX INTO V REGISTERS I==P4 ;I IN DO LOOPS J==N1 ;J IN DO LOOPS LEN==CH ;LENGTH OF ENTRIES DAT1==P ;DATA AC DAT2==F ; .. DAT3==P2 ; .. DAT4==P3 ; .. IC==T4 ;SAME AS I, BUT CORRECTED IMC==U ;HOLDS I+M, BUT CORRECTED ;ALL AC'S SAVED. SORT: PUSHJ P,SAVALL ;MAKE IT OK TO USE THEM ALL MOVEM P,TEMP1 MOVE LEN,LENGTH(KEY) ;SET UP CORRECT LENGTH MOVE DAT1,TEST(KEY) ;GET ADDRESS OF RIGHT TEST ROUTINE MOVEM DAT1,TESTX ;THIS FREES UP KEY AS ANOTHER GP AC HRLI V1,INDEX ;PUT INDEX INTO V1 SUBI V1,(LEN) MOVE V2,V1 AOS V3,V2 ;V2=V1+1 ADDI V3,1 ;V3=V1+2 HRRZ M,N ;M=N SORT1: LSH M,-1 ;M=M/2 JUMPE M,PPOPJ ;IF M=0, RETURN MOVEI J,1 ;J=1 SORT2: HRRZ I,J ;I=J SORT4: HRRZ IC,I IMULI IC,(LEN) ;IC=I, CORRECTED HRRZ IMC,I ADDI IMC,(M) IMULI IMC,(LEN) ;IMC=I+M, CORRECTED HRRZ INDEX,IC MOVE DAT1,@V1 ;DAT1 = V1(I) MOVE DAT3,@V2 ;DAT3 = V2(I) HRRZ INDEX,IMC MOVE DAT2,@V1 ;DAT2 = V1(I+M) MOVE DAT4,@V2 ;DAT4 = V2(I+M) JRST @TESTX ;GO COMPARE THESE TWO ENTRIES ;IF V(I) .LE. V(I+M) GOTO SORT3 ;ELSE, RETURN HERE AT SORT4A SORT4A: SUBI I,(M) ;I=I-M CAIL I,1 ;IF I .GE. 1, JRST SORT4 ; GOTO SORT4 SORT3: ;ADDI J,1 ;ALGORITHM SAYS DO THIS HERE, BUT WONT ;CAUSE WILL BE TRICKY HRRZ DAT1,N SUBI DAT1,1(M) ;DAT1=N-M (ACTUALLY N-M-1, THATS THE TRICK) CAILE J,(DAT1) ;J .GT. N-M?? AOJA J,SORT1 ;YES. GOTO SORT1 AOJA J,SORT2 ;NO. GOTO SORT2 PPOPJ: MOVE P,TEMP1 ;RESTORE P POPJ P, ;AND GO HOME... TEST: TEST0 TEST1 TEST2 U(TESTX) LENGTH: 2 2 3 ;HERE IF KEY=0, SORT 2 WORD ENTRIES ON BOTH WORDS (/AF) TEST0: CAMGE DAT1,DAT2 ;V1(I) .LT. V1(I+M) ?? JRST SORT3 ;DEFINITELY YES. GOTO SORT3 CAME DAT1,DAT2 ;IF EQUAL, MUST TEST SECOND WORD JRST FLIP ;NOT EQUAL. GO FLIP THEM. CAMG DAT3,DAT4 ;V2(I) .LT. V2(I+M)?? JRST SORT3 ;FIRST HALF EQUAL, SECOND HALF V(I) IS ; .LE. , SO ENTIRE ENTRY IS .LE., GOTO SORT3 ;HERE TO SWITCH THE TWO ENTRIES FLIP: MOVEM DAT1,@V1 ;STORE V1(I) INTO V1(I+M) MOVEM DAT3,@V2 ;STORE V2(I) INTO V2(I+M) HRRZ INDEX,IC MOVEM DAT2,@V1 ;STORE V1(I+M) INTO V1(I) MOVEM DAT4,@V2 ;STORE V2(I+M) INTO V2(I) JRST SORT4A ;AND CONTINUE IN MAINSTREAM OF PROGRAM ;HERE ON KEY=1, SORT 2 WORD ENTRIES ON LEFT HALF OF SECOND WORD AND ;WHOLE FIRST WORD (/AE) TEST1: MOVEM DAT3,TEMP2 HLRZS DAT3 ;ZERO CFP'S HLRZS DAT4 CAIGE DAT3,(DAT4) ;EXT(I) .LT. EXT(I+M) ??? JRST SORT3 ;DEFINITELY YES. GOTO SORT3 CAIE DAT3,(DAT4) ;EQUAL EXTENSIONS? JRST .+3 ;NO. EXT(I) .GT. EXT(I+M), SO SWITCH THEM CAMG DAT1,DAT2 ;EXTENSIONS EQUAL. COMPARE FILENAMES JRST SORT3 ;NAME(I) .LE. NAME(I+M). GOTO SORT3 ;HERE IF MUST SWITCH THE TWO ENTRIES MOVE DAT4,@V2 ;GET BACK DAT4 MOVE DAT3,TEMP2 ;GET BACK DAT3 JRST FLIP ;AND GO SWITCH THEM. ;HERE ON KEY=2, SORT THREE WORD ENTRIES ON THIRD WORD (/AT) TEST2: MOVE TMP,@V3 ;TMP=V3(I+M) HRRZ INDEX,IC CAML TMP,@V3 ;IS V3(I) .GE. V3(I+M)? JRST SORT3 ;YES. NO SWITCH ;HERE TO SWITCH THREE ENTRIES EXCH TMP,@V3 ;STORE V3(I+M) INTO V3(I) HRRZ INDEX,IMC MOVEM TMP,@V3 ;STORE V3(I) INTO V3(I+M) JRST FLIP ;AND GO SWITCH THE OTHER TWO ENTRIES SUBTTL Core allocation routine ; Subroutine to allocate core. ; Call T=Number of words needed ; Ret+0 always with T=address of first location of new core ; C(.JBFF)=Adr. of last new loc + 1 CORGRB: JSP M,SAVE3 JSP M,TTYOUT MOVE P1,T ADD T,.JBFF ; P1=Highest core needed CAMG T,.JBREL ; Already have it? JRST CORGR2 ; Yes. Don't need UUO CORGR1: SKIPL %LOCK ; Locked in core? JRST .+4 ; No. No problem MOVE N,ONEONE UNLOK. N, ; Yes. Unlock us for a while... JFCL CORE T, ; Ask for core now JRST NOCORE SKIPL %LOCK ; We locked? JRST CORGR4 PUSHJ P,LOCKUUO ; Yes. Re-lock us with new core now.. SKIPA JRST CORGR4 SETZM %LOCK MOVEI M,[ASCIZ/Cannot remain locked in core. Continuing unlocked!/] PUSHJ P,MSGTTY PUSHJ P,CRLF CORGR4: TXOA F,F.TMP ; Remember that we did UUO CORGR2: TXZ F,F.TMP ; We didnt do UUO MOVE P2,.JBFF ; Save first adr in P2 ADDM P1,.JBFF ; Increment to new .JBFF TXZE F,F.TMP ; Did we do UUO?? PUSHJ P,PNTCOR ; Yes. Tell him MOVEI T,1(P2) ; Restore T and inc it one HRLI T,(P2) ; T=adr of new core,, adr+1 SETZM (P2) BLT T,@.JBFF ; Clear all new core MOVEI T,(P2) ; Restore T POPJ P, ; and give normal return ; Here if core not available... back up 5 yards and punt NOCORE: MOVEI M,[ASCIZ/ can't get core, change CORMAX and then try ^C .CONTINUE to resume operation. /] PUSHJ P,MSG MONRT. ; Exit, allow continue MOVE T,P1 ; To continue here ADD T,.JBFF JRST CORGR1 ; and try more ; (He can try core command) ; Subroutine to print size of core now PNTCOR: JSP M,TTYOUT PUSHJ P,CRLF MOVEI CH,"[" PUSHJ P,W.CMD MOVE N,.JBREL ADD N,COREXX SUBI N,1 IDIV N,COREXX PUSHJ P,DECPR1 ; Print decimal without dot IFN PURESW,< MOVEI CH,"+" PUSHJ P,W.LST MOVEI N,RIPEND-400000-1 ADD N,COREXX IDIV N,COREXX PUSHJ P,DECPR1 > ;END IFN PURESW MOVEI CH,"K" MOVEI N,^D512 CAMN N,COREXX MOVEI CH,"P" PUSHJ P,W.LST MOVEI M,[ASCIZ . core] .] PJRST MSG ; And return ; Subroutine to reduce core to minimum. ; Call before increasing core (calling CORGRB) ; Do MOV .JBFF,.SFVV to save .JBFF ; Then call ZCORE which restores it to .SVFF ; ZCORE: MOVE T1,.JBREL MOV .SVFF,.JBFF CORE T, JFCL CAME T1,.JBREL ; Has .JBREL changed? PUSHJ P,PNTCOR ; Yes. Tell him POPJ P, SUBTTL Block printing routines ; Subroutine to print a home block ; Call U=UDB address of unit ; Ret+0 always with ; home block in BUF, printed to listing file too... PNTHOM: PUSHJ P,HOMCHK ; Go read home blocks JRST DIE004 ; Just can't happen MOVEI M,[ASCIZ/ HOME block /] PUSHJ P,MSG PJRST BLKPRT ;SUBROUTINE TO LOOK AT 'USRPPN' AND SEE IF IT IS ANY OF ;THE IMPORTANT PPN'S (EG, 1,1 1,4 OR 1,2). CHKPPN: JSP M,SAVE3 MOVE P1,USRPTH+.PTPPN ; MOVEI P2,NUMPPN-1 ;4 PPNS TO LOOK AT CHKPP1: MOVE P3,VIPPNS(P2) ;GET ADR OF PPN MOVE P3,(P3) ;GET PPN CAMN P3,P1 ;IS IT ONE? JRST CHKPP2 ;HELL YES. SOJGE P2,CHKPP1 ;REPEAT FOR EACH ONE. JRST CPOPJ1 ;AOK.. CHKPP2: MOVEI M,[ASCIZ/ Access files from /] PUSHJ P,MSGTTY ;INFORM HIM THIS IS A NO NO. PUSHJ P,UFDPNT ; Print offending path MOVEI M,[ASCIZ/?/] PJRST OPER ;AND CHECK WITH THE DODO VIPPNS: QUEPPN MFDPPN SYSPPN FSFPPN CRSPPN NUMPPN==.-VIPPNS ;SUBROUTINE TO PRINT A BLOCK OF 200 WORDS IN BUF ;CALL BLKPRT TO PRINT BUFSIZ=200 WORDS IN BUF ; BLKPN1 TO PRINT C(P2) WORDS WITH P1=AOBJN PTR TO THOSE WORDS BLKPRT: JSP M,SAVE3 MOVEI P2,BLKSIZ ;P2 HAS # OF WORDS TO BE PRINTED MOVN P1,P2 HRLZS P1 HRRI P1,BUF ;P1 IS AOBJN PTR TO BUF PUSHJ P,HEDBLK BLKPN1: HRLM P1,(P) ;SAVE ADDRESS OF FIRST WORD SETZ P3, ;ZERO COUNTER. BLKPN3: TRNN P3,7 PUSHJ P,CRLF ;CRLF EVERY 8 WORDS MOVE N,(P1) PUSHJ P,OCTL12 PUSHJ P,SPC ADDI P3,1 ;INC COUNT FOR EVERY 8 WORDS TEST AOBJN P1,BLKPN3 HLRZ P2,(P) ;GET BACK ADDRESS OF FIRST WORD SUB P2,P1 ;SUBTRACT LAST WORD ADDRESS+1 ADDI P2,BLKSIZ ;P2=BLKSIZ-# OF WORDS PRINTED ;=NUMBER OF WORDS OF DOTS TO PRINT JUMPLE P2,CRLF2 ;DONE ALREADY. FORGET DOTS BLKPN2: TRNN P3,7 PUSHJ P,CRLF MOVEI M,^D12 MOVEI CH,"." PUSHJ P,W.LST ;WRITE 12 DOTS FOR REMAINING WORDS SOJG M,.-1 PUSHJ P,SPC ADDI P3,1 SOJG P2,BLKPN2 PJRST CRLF2 ;AND FINISH OFF WITH CRLF ;SUBROUTINE TO PRINT 200 WORD BLOCK IN BUFF IN ASCII FORMAT ASCOUT: TXNE F,F.CRLF ;SUPPRESS CRLF?? JRST .+3 ;YES. PUSHJ P,HEDBLK ;HEADER FOR BLOCK PUSHJ P,CRLF2 MOVE T,[POINT 7,BUF] HLRE T1,IOW IMULI T1,5 ;5 CHARS/WORD HRLZS T1 ;T1 COUNTS CHARS ILDB CH,T ;GET A CHAR PUSHJ P,W.LST ;WRITE IT AOBJN T1,.-2 ;AND CONTINUE TXNN F,F.CRLF PJRST CRLF2 ;UNTIL DONE POPJ P, ;SAME ROUTINE AS ABOVE, ONLY SIXBIT INSTEAD OF ASCII... SIXOUT: PUSHJ P,HEDBLK PUSHJ P,CRLF2 MOVE T,[POINT 6,BUF] HLRE T1,IOW IMULI T1,6 HRLZS T1 ILDB CH,T ADDI CH,40 ;SIXBITIZE PUSHJ P,W.LST AOBJN T1,.-3 PJRST CRLF2 ;SUBROUTINE TO PRINT 200 WORD BUFFER AS IF IT WAS A DIRECTORY ;PRINTS FILE,EXT,LOG BLOCK IN STR, REL BLOCK IN UNIT, UNIT DIRPRT: PUSHJ P,HEDBLK MOVEI M,DIRPM ;PRINT HEADER PUSHJ P,MSG MOVE T2,IOW ;T1 COUNTS WORDS DIRP1: MOVE T,1(T2) ;FILE NAME HLLZ T1,2(T2) ;AND EXTENSION JUMPE T,DIRP2 ;IGNORE NULL FILE NAMES PUSHJ P,NAMPNT ;GO PRINT THEM HRRZ T,2(T2) ;AND THE CFP PUSHJ P,CFP2BK ;CONVERT TO LOG BLOCKS MOVE N,T1 ;N=REL BLOCK ON UNIT PUSHJ P,OCTPRT ; PUSHJ P,TAB MOVE N,T ;GET LOG BLOCK IN STR AGAIN PUSHJ P,OCTPRT ; PRINT LOG BLOCK PUSHJ P,TAB MOVE N,HOMLUN(U) PUSHJ P,OCTPRT ;AND UNIT # PUSHJ P,CRLF DIRP2: AOBJN T2,.+1 AOBJN T2,DIRP1 POPJ P, ;DONE.. ;HERE ON /PR - PRINT BUF AS A RIB RIBPNT: TXZ F,F.NEWR ;SET BY GETPTR IF READS NEW RIB HRRZ T,BUF+RIBCOD ;CHECK CODE WORD CAIE T,CODRIB JRST RIBPN1 ;NOT A RIB! MOV BUF+RIBNAM,USRNAM MOVE T,BUF+RIBEXT HLLZM T,USREXT MOV BUF+RIBPPN,USRPTH+.PTPPN ; RIBPN0: PUSHJ P,CRLF PUSHJ P,FILPNT ;PRINT FILE NAME,EXT,PPN PUSHJ P,UFDPNT PUSHJ P,TAB PUSHJ P,DIRLST ;(CREATION & ACCESS TIMES, DATE,MODE) PUSHJ P,CRLF2 PUSHJ P,HEDBLK ;TELL HIM WHAT BLOCK THIS IS PUSHJ P,CRLF MOVE T,[RIBTAB,,BUF+RIBSIZ] TXO F,F.TMP ;SUPPRESS PRINTING ZERO WORDS PUSHJ P,LSTPNT ;PRINT RIBSIZ THROUGH RIBTIM MOVE T,[RIBTB1,,BUF+RIBLAD] ; HRRZ T1,BUF+RIBFIR ;RIBFIR HAS RELATIVE ADDRESS OF PTRS CAIL T1,RIBACT ; Earlier than 603? PUSHJ P,LSTPNT ; Nope, print info MOVEI M,RIBHED PUSHJ P,MSG TXZE F,F.NEWR JRST [POP P,P1 ;IF FLAG SET, SKIP COPY JRST RIBPN4] ;CAUSE GETPTR HAS ALREADY DONE SO MOVEI P4,DSK PUSHJ P,PTRCPY ;PUT RIB INTO DSK BLOCK RIBPN2: PUSHJ P,GETPTR ;GET A POINTER JUMPE P1,RIBPN3 ;DONE IF NO POINTER TXNE F,F.NEWR ;WE JUST READ A NEW RIB? JRST [PUSH P,P1 ;YES. SAVE PTR PUSHJ P,CRLF3 ;PRINT ANOTHER HEADER JRST RIBPN0] RIBPN4: MOVE N,P1 PUSHJ P,OCTL12 ;PRINT POINTER PUSHJ P,TAB LDB N,STRCLP IMUL N,STRBPC MOVE T1,N PUSHJ P,OCTPRT ; PRINT BLOCK ADR PUSHJ P,TAB MOVE N,HOMLUN(U) IMUL N,STRBPU ADD N,T1 PUSHJ P,OCTPRT ; REL BLOCK IN STR PUSHJ P,TAB MOVE N,P2 IMUL N,STRBPC PUSHJ P,DECPRT ;PRINT # OF CONTIGIOUS BLOCKS PUSHJ P,TAB PUSHJ P,SPC2 MOVE N,HOMLUN(U) PUSHJ P,OCTPRT ;PRINT UNIT PUSHJ P,TAB ; PUSHJ P,SPC2 ; LDB N,STRCKP ; Get checksum from pointer PUSHJ P,OCTPRT ; and print it PUSHJ P,CRLF JRST RIBPN2 ;CONTINUE FOR ALL POINTERS RIBPN1: MOVEI M,[ASCIZ/Specified block is not a RIB/] PJRST MSGTTY RIBPN3: POP P,BUF+RIBFIR POPJ P, RIBTAB: DEFINE TABMAC (X,Y) < XWD [ASCIZ\X\] , Y > TABMAC Words written, DECPRT TABMAC Version, HALF8 TABMAC Spooled dev, NPR6BT TABMAC Est. block length, DECPRT TABMAC Blocks allocated, DECPRT TABMAC Logical block in STR of last group, OCTPRT TABMAC Future arg for DEC, OCTL12 TABMAC Non-priv customer arg, OCTL12 TABMAC Tape label, NPR6BT TABMAC Structure, NPR6BT TABMAC Status bits, HALF8 TABMAC First block bad region, OCTPRT TABMAC RIBEUN,HALF8 TABMAC FCFS quota, DECPRT TABMAC Logged out quota, DECPRT TABMAC Reserved quota, DECPRT TABMAC No. blocks used when last logged out, DECPRT TABMAC Author, OCTPPN TABMAC Next STR, NPR6BT TABMAC Prev. STR, NPR6BT TABMAC Privileged customer arg, OCTL12 TABMAC UFD block with ptr to this RIB, OCTPRT TABMAC First logical block in RIB, OCTPRT TABMAC Extended RIB address, OCTL12 TABMAC ,DATTIM Z ;ENDS THE LIST! RIBTB1: TABMAC Last accounting date, DATTIM TABMAC Directory expiration date, DATTIM TABMAC AOBJN pointer to accounting string, OCTL12 Z ; Ends the list ; The following table is for printing the unit UDB'S ; used in /PV code. UNITAB: TABMAC System ID , NPR6BT ;HOMHID=1 TABMAC Physical address of HOME blocks , HALF8 ;HOMPHY=2 TABMAC Position of STR in SYS search list , OCTPRT ;HOMSRC=3 TABMAC Structure name , NPR6BT ;HOMSNM=4 TABMAC ID next unit in STR , NPR6BT ;HOMNXT=5 TABMAC ID previous unit in STR , NPR6BT ;HOMPRV=6 TABMAC Logical unit in STR , NPR6BT ;HOMLOG=7 TABMAC Unit in STR , OCTPRT ;HOMLUN=10 TABMAC PPN which refreshed STR , OCTPPN ;HOMPPN=11 XWD Z , CPOPJ ;HOMHOM=12 TABMAC Number of blocks/group to try for on output , DECPRT ;HOMGRP=13 TABMAC Blocks/supercluster , DECPRT ;HOMBSC=14 TABMAC Superclusters/unit , DECPRT ;HOMSCU=15 TABMAC RIB byte pointer for cluster count , BYTPNT ;HOMCNP=16 TABMAC RIB pointer for checksum , BYTPNT ;HOMCKP=17 TABMAC RIB pointer for cluster address , BYTPNT ;HOMCLP=20 TABMAC Blocks per cluster , DECPRT ;HOMBPC=21 TABMAC K for swapping on unit , K4SPNT ;HOMK4S=22 TABMAC HOMREF (non-zero if refresh needed) , OCTPRT ;HOMREF=23 TABMAC Number of SAT blocks in core , DECPRT ;HOMSIC=24 TABMAC Unit ID of next unit in active swapping list , NPR6BT ;HIMSID=25 TABMAC Logical unit # in active swapping list , OCTPRT ;HOMSUN=26 TABMAC First log block number for swapping on unit , OCTPRT ;HOMSLB=27 TABMAC Swapping class , OCTPRT ;HOMCFS=30 TABMAC Number of SAT blocks/unit , DECPRT ;HOMSPU=31 TABMAC Blocks reserved for overdraw per user , DECPRT ;HOMOVR=32 TABMAC Sum of blocks guarenteed to users , DECPRT ;HOMGGAR=33 TABMAC , OCTPRT TABMAC < HOME.SYS> , OCTPRT TABMAC < SWAP.SYS> , OCTPRT TABMAC < MAINT.SYS> , OCTPRT TABMAC < BADBLK.SYS> , OCTPRT TABMAC < CRASH.SAV> , OCTPRT TABMAC < SNAP.SAV> , OCTPRT TABMAC < RECOV.SYS> , OCTPRT TABMAC < SYS UFD> , OCTPRT TABMAC < QUEUE UFD> , OCTPRT TABMAC < MFD > , OCTPRT TABMAC First retrieval ptr for MFD , OCTL12 TABMAC Logical unit where MFD starts , OCTPRT TABMAC , DECPRT TABMAC < SNAP.SAV> , DECPRT TABMAC < RECOV.SYS> , DECPRT TABMAC < SYS UFD> , DECPRT TABMAC < QUEUE UFD> , DECPRT TABMAC < MFD> , DECPRT ; The following words defined in the UDB alone, not from home blocks TABMAC Words/SAT , DECPRT TABMAC Clusters/SAT , DECPRT TABMAC Physical unit name (drive) , NPR6BT TABMAC , HALF8 TABMAC Blocks/cylinder , DECPRT TABMAC Blocks/track , DECPRT TABMAC Blocks on unit , DECPRT Z ;ENDS THE LIST!!! ;SUBROUTINE TO PRINT A BLOCK OF DATA WITH MESSAGES FOR EACH WORD ;CALL F.TMP = 1 TO SUPRESS LISTING ZERO WORDS ; LH(T) = ADR. OF TABLE ; RH(T) = ADR OF DATA ; ;TABLE ENTRIES ARE OF FORMAT: ; LH - [ASCIZ\ARBITRARY MESSAGE\] ; RH - ROUTINE TO PRINT DATA IN AC N ; ;IF LH = Z, RH=Z MEANS END OF LIST, RH=NON-ZERO MEANS SKIP WORD. ;IE, XWD Z , CPOPJ ;SKIP WORD ; Z ;END OF LIST LSTPN1: AOBJN T,.+1 ;POINT TO NEXT ENTRY LSTPNT: HLRZ T1,T ;T1=ADR OF TABLE HLRZ M,(T1) ;M=ADR OF MESSAGE TO PRINT JUMPE M,LSTPN2 ;OR ZERO IF END OF LIST OR SKIP WORD SKIPN N,(T) ;N=WORD TO PRINT. ZERO?? TXNN F,F.TMP ;YES. ARE WE TO SUPRESS ZEROES? SKIPA ;NO TO EITHER. PRINT IT JRST LSTPN1 ;YES TO BOTH. IGNORE THIS WORD PUSHJ P,MSG ;PRINT MSG PUSHJ P,EQUAL HRRZ T1,(T1) ;ADR. OF WHERE TO GO PUSH P,T ;SAVE OUR ONE IMPORTANT AC PUSHJ P,(T1) ;GO THERE AND PRINT POP P,T PUSHJ P,CRLF JRST LSTPN1 ;HERE IF ZERO LEFT HALF LSTPN2: SKIPN (T1) ;WHOLE WORD ZERO? POPJ P, ;YES. DONE JRST LSTPN1 ;NO. JUST IGNORE IT HEDBLK: MOVEI M,[ASCIZ/ [Logical block /] PUSHJ P,MSG MOVE N,CURPOS(U) ;CURRENT BLOCK JUST READ PUSHJ P,OCTPRT ; MOVEI M,[ASCIZ/ on /] PUSHJ P,MSG SKIPN M,HOMLOG(U) MOVE M,DRIVE(U) PUSHJ P,PR6BIT PUSHJ P,RBRKT ;CLOSING BRACKET PJRST CRLF ;SUBROUTINE TO PRINT A BYTE POINTER. PRINTS A ;12 DIGIT OCTAL NUMBER WITH ONES IN THE BYTE POSITION. ;EG, POINT 4,XYZ,8 PRINTS 017000000000 BYTPNT: HRRI N,N1 ;MAKE PTR POINT TO N1 SETO N1, ;N1:=ALL ONES LDB N1,N ;N1:=AS MANY ONES AS BYTE LENGTH LDB N,[POINT 6,N,5] ;N:=BYTE POSITION=35-RIGHTMOST BIT LSH N1,(N) ;SHIFT N1 OVER TO BYTE POSITION MOVE N,N1 ;AND PUT IT INTO N FOR PRINTING PJRST OCTL12 ;AND PRINT IT SUBTTL Error processing routines ; Here for various command string error messages CMDERR: JSP M,CMDER1 ASCIZ/?Command error/ CMDER1: MOV <[POINT 1,ZERO]> , CMDB PJRST ERR000 BADMON: JSP M,MSGXIT ASCIZ /?Must be level D or later/ BADBOY: OUTSTR [ASCIZ/?Job not privilleged/] EXIT NOTTY: OUTSTR [ASCIZ/?Can't OPEN TTY/] EXIT NOLPT: JSP M,MSGXIT ASCIZ /?Can't INIT listing device/ EFAIL: JSP M,MSGXIT ASCIZ /?Listing file ENTER failed/ BADSW: JSP M,CMDER1 ASCIZ/?Bad switch/ BADCFG: JSP M,MSGXIT ASCIZ/?SFD configuration error - check SFDLVL parameter/ ; Various error messages. JRST RIPDON when done ERR000: PUSHJ P,MSGTTY PUSHJ P,CRLF OUTPUT CMD, JRST RIPDON ERR001: JSP M,ERR000 ASCIZ /?Bad option/ ERR002: JSP M,ERR000 ASCIZ /?File name arg illegal/ ERR003: JSP M,ERR000 ASCIZ/?INIT failure on scratch device/ ERR004: JSP M,ERR000 ASCIZ/?ENTER failure on scratch file/ ERR005: JSP M,ERR000 ASCIZ/?No data input yet/ ERR006: JSP M,ERR000 ASCIZ/?Word must be 0-177/ ERR007: JSP M,ERR000 ASCIZ/?LOOKUP failure on scratch file/ ; Various error messages continued ERR008: JSP M,ERR000 ASCIZ/?SAT's not in core/ ERR009: JSP M,ERR000 ASCIZ/?SAT IOERR/ ERR010: JSP M,ERR000 ASCIZ/ Cannot rewrite SATS unless all files specified/ ERR011: JSP M,ERR000 ASCIZ\ /IF may only have one of S or R options\ ERR014: JSP M,ERR000 ASCIZ/?Can't find RIPOFF.HLP/ ERR015: JSP M,ERR000 ASCIZ\?Device must be a structure to fix SATs\ ERR016: JSP M,ERR000 ASCIZ\?Function illegal when structure is mounted\ ERR017: JSP M,ERR000 ASCIZ/?Device must be a structure/ ERR018: JSP M,ERR000 ASCIZ\?Cannot specify non-star SFD's with /DU\ ; Catastrophic error messages. DIE000: CLOSE LST, ; Close output file RELEAS LST, ; and release it RESET ; Stop the world the hard way OUTSTR (M) ; Type message EXIT ; and die JRST .-1 ; No restart DIE001: JSP M,DIE000 ASCIZ/? SUSET. UUO failed/ DIE002: JSP M,DIE000 ASCIZ/[User abort]/ DIE003: JSP M,DIE000 ASCIZ/? REWSTR failed/ DIE004: JSP M,DIE000 ASCIZ/? Internal UDB's messed up/ DIE005: JSP M,DIE000 ASCIZ/[AUX device abort]/ DIE006: JSP M,DIE000 ASCIZ/? NXTSTR OPEN failed/ ; Questionable operation messages. POPJ when done MSG000: PUSH P,F PUSHJ P,MSGTTY PUSHJ P,CRLF OUTPUT CMD, ; Yes. Make sure message gets out POP P,F POPJ P, ; and return MSG001: JSP M,MSG000 ASCIZ/Wait plz.../ ; Various operator questions. If answer is yes, return+0. ; If answer no, JRST RIPDON.. Flags preserved, AC's M,CH destroyed. ; All others preserved. ASK000: PUSHJ P,OPER JRST RIPDON POPJ P, ASK001: JSP M,ASK000 ASCIZ/Not same STR/ ASK002: JSP M,ASK000 ASCIZ/Not same block/ ASK003: JSP M,ASK000 ASCIZ/Wipe out all files? Are you sure? / ASK004: JSP M,ASK000 ; ASCIZ /Device is not a structure/ ASK005: JSP M,ASK000 ; ASCIZ\Write listing to same structure on which /V is being done? If no, type: ^C ASSIGN dev LST RUN RIPOFF\ SUBTTL I/O routines for operator communication ;SUBROUTINE TO ASK OPERATOR TO CONTINUE OR NOT. ;RET+0 IF NOT, ;RET+1 IF HE SAYS YES OPER: PUSHJ P,SAVALL MOVEM M,TEMP JSP M,TTYOUT OPER2: MOVE M,TEMP PUSHJ P,MSGTTY MOVEI M,[ASCIZ/ Proceed? /] PUSHJ P,MSG OUTPUT CMD, SETZM RH.CMD+2 ;NO TYPEAHEAD. MOV <[POINT 1,ZERO]> , CMDB CLRBFI PUSHJ P,R.CMD SETZM RH.CMD+2 ; Clear all typeahead CLRBFI CAIN CH,"Y" JRST CPOPJ1 CAIE CH,"N" JRST OPER2 ;MUST SAY ONE OR OTHER POPJ P, ;SUBROUTINE TO CHECK THAT BOTH NAME AND EXT ARE STARS. ;RET+0 IF EITHER NOT STAR. ;RET+1 IF ALL STARS NONAME: TXNN F,S.NAM POPJ P, TXNN F,S.EXT POPJ P, JRST CPOPJ1 ;PRINT A "FILE.EXT" FILPNT: MOVE T,USRNAM HLLZ T1,USREXT ;ROUTINE TO PRINT A FILE.EXT WITH FILE NAME IN T AND EXT IN T1. ; Call with F.FNOTB set to print with dot between filename and ; extension instead of TAB. NAMPNT: LDB M,[POINT 6,T,5] ;GET FIRST 6 BIT CHAR PUSHJ P,NAMTST ;SKIP IF SIXBIT JRST NAMP1 ;NOT SIXBIT. LOOK CLOSER. NAM6BT: MOVE M,T ;PRINT IT AS SIXBIT. TXZE F,F.NOTB ; Print with dot? JRST NAM6B1 ; Yep, go do it PUSHJ P,PR6ALL NAMEXT: PUSHJ P,TAB HLLZ M,T1 ;EXTENSION WILL ALWAYS BE SIXBIT PJRST PR6ALL NAM6B1: PUSHJ P,PR6BIT ; Print as SIXBIT NAMEX1: PUSHJ P,DOT ; Followed by dot HLLZ M,T1 ; Get ext PJRST PR6BIT ; And print in SIXBIT also NAMP1: CAIE M,'.' ;THE ONLY SIXBIT CHAR WHICH IS NOT ;A-Z,0-9 AND STILL IN FILENAMES. JRST NAMOCT ;NOT A DOT, PRINT IT IN OCTAL LDB M,[POINT 6,T,11];TRY SECOND CHAR THEN. PUSHJ P,NAMTST SKIPA ;NOT A-Z,0-9. REALLY OCTAL THEN JRST NAM6BT ;AOK. PRINT 6BIT NAMOCT: MOVE N,T PUSHJ P,HALF8 TXZN F,F.NOTB ; Print dot or tab? JRST NAMEXT ; tab JRST NAMEX1 ; dot NAMTST: CAIL M,'0' CAILE M,'Z' POPJ P, CAIGE M,'A' CAIG M,'9' JRST CPOPJ1 POPJ P, ; Routine to print the current path from USRPTH. Stops on a zero ; word or the nesting specified by CURLVL, whichever comes first. UFDPNT: MOVEI CH,"[" PUSHJ P,W.LST ; Start with "[" PUSH P,P1 ; Get a pointer to use PUSH P,P2 ; Plus limit word MOVE P2,CURLVL ; Get current level of nesting ADDI P2,USRPTH+.PTPPN ; Compute max offset MOVEI P1,USRPTH+.PTPPN; Get pointer to start of path MOVE N,(P1) ; Get PPN PUSHJ P,OCTPPN ; and print in octal UFDPN2: CAML P1,P2 ; Done yet? JRST UFDPN3 ; Yep MOVE M,1(P1) ; Get next SFD name JUMPE M,UFDPN3 ; If we have reached the end PUSHJ P,COMMA ; Make it look good PUSHJ P,PR6BIT ; Type name AOJA P1,UFDPN2 ; Loop for all UFDPN3: POP P,P2 ; Restore P2 POP P,P1 ; Restore P1 PJRST RBRKT ; Finish off with right bracket ; Routine to print FILE.EXE[path] of file LOOKed UP ; on channel (P4). Set at LOOKP. CHNPNT: MOVX T,IO.FAC TDNN T,IOSTS(P4) ; File active on this channel? POPJ P, ; No. Forget it MOVE T,FNAME(P4) HLLZ T1,FEXT(P4) TXO F,F.NOTB ; Use dot instead of tab PUSHJ P,NAMPNT ; Print name.ext MOVEI CH,"[" PUSHJ P,W.LST MOVE N,FPATH+.PTPPN(P4) PUSHJ P,OCTPPN ; Print [P,PN] PUSH P,P1 ; Get an index to use MOVEI P1,FPATH+.PTPPN+1(P4) ; Point to first SFD word CHNPN1: SKIPN M,(P1) ; Skip if next SFD is non-null JRST CHNPN2 ; At end of path if null SFD PUSHJ P,COMMA ; Print a comma PUSHJ P,PR6BIT ; Print the SFD name AOJA P1,CHNPN1 ; and loop for all CHNPN2: POP P,P1 ; Restore P1 MOVEI CH,"]" PJRST W.LST ; Subroutine to set TTY I/O and reset flags after return to lower ; level of pushdown. Call JSP M,TTYOUT TTYOUT: PUSH P,F ; Put flags onto stack ANDI F,F.TTY!F.TTY2 ; F:=State of TTY flags only EXCH F,(P) ; Get back flags, stack TTY state TTYON ; Turn on TTY I/O PUSHJ P,(M) ; Return to caller SKIPA AOS -1(P) TTYOFF ; Shut off TTY now. TDO F,(P) ; Reset TTY state before call SUB P,ONEONE ; Reset pushdown depth POPJ P, ; and return to higher caller ;ROUTINE TO PRINT AN ERROR CODE IN AC N ALONG WITH ANY MESSAGE ;CALL: RH(T) = ADR. OF MESSAGE TABLE ; LH(T) = NUMBER OF HIGHEST ERROR IN TABLE ; ; MESSAGE TABLE SHOULD LOOK LIKE: ; XWD [ASCIZ/MSG1/] , [ASCIZ/MSG2/] ; ERRPNT: MOVEI M,[ASCIZ/ (/] PUSHJ P,MSG ;GIVE OPENING PAREN MOVE P1,N ;SAVE ERROR CODE PUSHJ P,OCTPRT ;AND PRINT IT HLRZ T1,T ;GET MAX # OF ERRORS CAMG P1,T1 ;CAN WE PRINT A SPECIFIC MESSAGE? JRST ERRPN1 ;YES. GO DO IT. ERRPN2: MOVEI M,[ASCIZ/) error code /];NO. JUST SAY IT IS AN ERROR MOVE N,P1 ;RESTORE N PJRST MSG ;AND RETURN ERRPN1: MOVEI M,[ASCIZ/) /] ;CLOSING PAREN PUSHJ P,MSG MOVE N,P1 ;RESTORE N HRRZS T ;T=ERROR TABLE ADR. IDIVI P1,2 ADDI P1,(T) ;P1=ADR. OF THIS ERROR MESSAGE SKIPE P2 ;IF N WAS ODD, SKIPA M,(P1) ;USE RH OF TABLE ENTRY. HLRZ M,(P1) ;IF N EVEN, USE LH OF TABLE JUMPE M,ERRPN2 ;IF ZERO, GIVE GENERAL MESSAGE ONLY PJRST MSG ;PRINT IT AND RETURN TO CALLER ;ROUTINE TO PRINT ASCIZ MESSAGES POINTED TO IN "M" EMSG: TXOA F,F.ERRM ;SET FOR ERROR MESSAGES MSGTTY: TTYON ;FORCE TTY MESSAGES MSG: HRLI M,(POINT 7,0) MSGL: ILDB CH,M JUMPE CH,CPOPJ PUSHJ P,W.LST JRST MSGL CPOPJ1: AOSA (P) ;GIVE SKIP RETURN T1POPJ: POP P,T1 ; CPOPJ: POPJ P, UPOPJ1: AOS -1(P) ; Bump return point UPOPJ: POP P,U ; Restore U POPJ P, ; and return ;ROUTINES TO PRINT SPECIAL CHARACTERS EQUAL: JSP M,MSG ASCIZ/ = / ECRLF: TXO F,F.ERRM PJRST CRLF CRLF3: PUSHJ P,CRLF CRLF2: PUSHJ P,CRLF CRLF: JSP M,MSG ASCIZ/ / %CRLF: JSP M,MSG ASCIZ /% / SPC2: PUSHJ P,SPC SPC: SKIPA CH,[" "] FORM: MOVEI CH,.CHFFD PJRST W.LST COMMA: SKIPA CH,[","] DOT: MOVEI CH,"." PJRST W.LST TAB2: PUSHJ P,TAB TAB: SKIPA CH,[.CHTAB] SLASH: MOVEI CH,"/" PJRST W.LST RPAR: SKIPA CH,[")"] DASH: MOVEI CH,"-" PJRST W.LST PLUS: SKIPA CH,["+"] RBRKT: MOVEI CH,"]" PJRST W.LST COLON: SKIPA CH,[":"] LPAR: MOVEI CH,"(" PJRST W.LST ; Print SIXBIT word in AC "N" NPR6BT: MOVE M,N ; and fall into PR6BIT ; Print SIXBIT word in AC "M" ; PR6BIT quits on first blank, PR6ALL prints all PR6ALL: TDZA T,T PR6BIT: SETO T, HRLM T,(P) ; Remember entry MOVE T,[POINT 6,M] PR6BT1: ILDB CH,T SKIPGE (P) ; Skip test if entry at PR6ALL JUMPE CH,CPOPJ ; Otherwize test. ADDI CH," " PUSHJ P,W.LST TLNE T,770000 JRST PR6BT1 POPJ P, ; Here to print AC N as a 12 digit octal number OCTL12: MOVEI M,^D12 OCTLL: MOVEI N1,6 ROTC N,3 MOVEI CH,(N1) PUSHJ P,W.LST SOJG M,OCTLL POPJ P, ; Here to print AC "N" as halfword octal OCTPPN: TDZA T,T ; Flag entry point HALF8: SETOM T ; Same here HRR T,N ; Save prog number for later PUSH P,T ; Save flag and prog number on stack HLRZS N ; Isolate proj number PUSHJ P,OCTPRT ; Print it PUSHJ P,COMMA ; Followed by comma SKIPGE (P) ; Skip second comma if entry at OCTPPN PUSHJ P,COMMA POP P,N ; Restore prog number HRRZS N ; and isolate it PJRST OCTPRT ; Routines to print right-justified integers ; Field width in AC "T" ; Number in AC "N" DECSPC: SKIPA CH,[" "] ; Decimal with leading spaces DECZRO: MOVEI CH,"0" ; Decimal with leading zeroes MOVEI M,^D10 JRST RJRDXP OCTSPC: SKIPA CH,[" "] ; Octal with leading spaces OCTZRO: MOVEI CH,"0" ; Octal with leading zeroes MOVEI M,^D8 RJRDXP: MOVE N1,M JUMPL N,RDXPRT+1 JUSTFY: SOJLE T,RDXPRT ; Right justify CAMGE N,N1 PUSHJ P,W.LST IMUL N1,M JRST JUSTFY OCTPRT: SKIPGE N ; Number have sign bit set? PJRST OCTL12 ; Yes, print all 12 digits MOVEI M,^D8 ; Get radix JRST RDXPR1 ; and print as octal DECPRT: PUSH P,[DOT] ; Print dot at end of dec. number DECPR1: MOVEI M,^D10 ; Here to print decimal numbers RDXPRT: SKIPGE N ; Number negative? PUSHJ P,DASH ; Yes, print minus MOVMS N ; Get absolute value RDXPR1: IDIVI N,(M) ; Divide by radix HRLM N1,(P) ; Save remainder SKIPE N ; Done? PUSHJ P,RDXPR1 ; No, call ourselves HLRZ CH,(P) ; Get number from stack ADDI CH,"0" ; Convert to ASCII JRST W.LST ; Print and return to caller SUBTTL Date routines for internal conversion ; Routine to set T3=Universal standard creation Date.Time word of a file. ; Uses RIBTIM if exists, else gets 12 or 15 bit old format and converts. FILDAT: JSP M,SAVE3 ; Save some AC's SKIPN T3,BUF+RIBTIM ; Got a universal date already? JRST FILDT0 ; No. Got to build one. HRRZ P1,BUF+RIBFIR CAILE P1,RIBTIM ; This an old style RIB? POPJ P, ; No. Date is valid. ; Here if not new style RIB, must build date.time word FILDT0: PUSH P,T1 ; Save T1,T2 PUSH P,T2 LDB T2,EXLLCD ; Get 12 low order bits of creation date LDB T1,EXLHCD ; plus 3 high order bits DPB T1,[POINT 3,T2,23] ; Make 15 bit date LDB T1,EXLCRT ; Get time IMULI T1,^D60*^D1000 ; T1=Time in milliseconds, T2=15 bit date FILDT1: PUSHJ P,.CNVDT ; Convert T1,T2 to universal date.time in T3 POP P,T2 POP P,T1 POPJ P, ; Restore AC's and return. ; Here to return T3=universal file access date ,, 0 time FILACD: JSP M,SAVE3 ; Save AC's SETZ T1, ; Set zero time LDB T2,EXLACD ; Get 15 bit date PUSH P,T1 PUSH P,T2 JRST FILDT1 ; and continue like FILDAT ; Here to print a universal date/time as dd-mmm-yy hh:mm:ss ; Call with date/time in N DATTIM: MOVE T3,N ; Where PRDATE and PRTIME wants it PUSH P,T3 ; Save it PUSHJ P,PRDATE ; Print the date POP P,T3 ; Restore the word PJRST PRTIME ; Print time and return ;SUBROUTINES TO CONVERT DATES FROM 15 BIT TO UNIVERSAL AND BACK. ;STOLEN FROM SCAN.MAC, COPYRIGHT DEC.... ; ;SUBROUTINE TO CONVERT FROM UNIVERSAL DATE.TIME WORD IN T3 TO 15 BIT ;RETURNS T1=MILLISECOND TIME (SINCE MIDNIGHT), T2= 15 BIT DATE. ; .CNTDT: MOVE T1,T3 ;DEC VERSION NEEDS IT IN T1, RIPOFF CALLS ;IT FROM T3 PUSH P,T1 ;SAVE TIME FOR LATER JUMPL T1,CNTDT6 ;DEFEND AGAINST JUNK INPUT HLRZ T1,T1 ;GET DATE PORTION (DAYS SINCE 1858) RADIX 10 ;**** NOTE WELL **** ADDI T1,365*400+24*4-<2001-1859>*365-<2001-1859>/4-31-30+17 ;MAKE INTO DAYS SINCE JAN 1, 1601 IDIVI T1,365*400+24*4+1 ;SEPARATE UNITS OF 400 LSH T1,2 ;MULT ANSWER BY 4 IDIVI T2,365*100+24 ;SEPARATE CENTURIES CAIN T2,4 ;SEE IF LAST ONE SOSA T2 ;YES--BACK OFF JRST .+2 ;CONTINUE SKIP MOVEI T3,365*100+24 ;SET TO FULL (LEAP) CENTURY ADD T1,T2 ;INCLUDE CENTURIES IN RESULT IMULI T1,25 ;MULT ANSWER BY 25 IDIVI T3,365*4+1 ;SEPARATE UNITS OF 4 ADD T1,T3 ;INCLUDE IN ANSWER LSH T1,2 ;MULT ANSWER BY 4 MOVE T3,T4 ;PROMOTE AC IDIVI T3,365 ;SEPARATE YEARS CAIN T3,4 ;SEE IF END OF LEAP YEAR SOSA T3 ;YES--BACK OFF YEAR JRST .+2 ;CONTINUE SKIP MOVEI T4,365 ;SET FOR END OF YEAR ADDI T1,1601(T3) ;GET REAL YEAR ;T1 HAS YEAR, T4 HAS DAY IN YEAR MOVE T2,T1 ;COPY YEAR TO SEE IF LEAP YEAR IDIVI T2,400 ;SEE IF MULT OF 400 JUMPE T3,CNTDT1 ;YES--PROCEED MOVE T2,T1 ;GET NEW COPY IDIVI T2,100 ;SEE IF MULT OF 100 JUMPE T3,[MOVEI T3,1 ;YES--FLAG AS NO L.Y. JRST CNTDT1] ;AND PROCEED MOVE T2,T1 ;GET NEW COPY IDIVI T2,4 ;SEE IF MULT OF 4 ;T3 IS 0 IF LEAP YEAR ;UNDER RADIX 10 **** NOTE WELL **** CNTDT1: SUBI T1,1964 ;SET TO SYSTEM ORIGIN IMULI T1,31*12 ;CHANGE TO SYSTEM PSEUDO DAYS JUMPN T3,CNTDT2 ;IF NOT LEAP YEAR, PROCEED CAIGE T4,31+29 ;LEAP YEAR--SEE IF BEYOND FEB 29 JRST CNTDT5 ;NO--JUST INCLUDE IN ANSWER SOS T4 ;YES--BACK OFF ONE DAY CNTDT2: MOVSI T2,-11 ;LOOP FOR 11 MONTHS CNTDT3: CAMGE T4,.MNTAB+1(T2) ;SEE IF BEYOND THIS MONTH JRST CNTDT4 ;YES--GO FINISH UP ADDI T1,31 ;NO--COUNT SYSTEM MONTH AOBJN T2,CNTDT3 ;LOOP THROUGH NOVEMBER CNTDT4: SUB T4,.MNTAB(T2) ;GET DAYS IN THIS MONTH CNTDT5: ADD T1,T4 ;INCLUDE IN FINAL RESULT CNTDT6: EXCH T1,(P) ;SAVE ANSWER, GET TIME TLZ T1,-1 ;CLEAR DATE MUL T1,[24*60*60*1000] ;CONVERT TO MILLI-SEC. ASHC T1,17 ;POSITION RESULT POP P,T2 ;RECOVER DATE POPJ P, ;RETURN ;UNDER RADIX 10 **** NOTE WELL **** ;.CNVDT -- CONVERT 12 OR 15 BIT DATE TO UNIVERSAL DATE ;CALL: MOVE T1,TIME IN MILLISEC. ; MOVE T2,DATE IN 12 OR 15 BIT FORMAT ; PUSHJ P,.CNVDT ;RETURNS WITH RESULT IN T3 (.GT.0; OR -1 IF BEYOND SEPT. 27,2217) .CNVDT: PUSH P,T1 ;SAVE TIME FOR LATER IDIVI T2,12*31 ;T2=YEARS-1964 CAILE T2,2217-1964 ;SEE IF BEYOND 2217 JRST GETNW2 ;YES--RETURN -1 IDIVI T3,31 ;T3=MONTHS-JAN, T4=DAYS-1 ADD T4,.MNTAB(T3) ;T4=DAYS-JAN 1 MOVEI P1,0 ;LEAP YEAR ADDITIVE IF JAN, FEB CAIL T3,2 ;CHECK MONTH MOVEI P1,1 ;ADDITIVE IF MAR-DEC MOVE T1,T2 ;SAVE YEARS FOR REUSE ADDI T2,3 ;OFFSET SINCE LEAP YEAR DOES NOT GET COUNTED IDIVI T2,4 ;HANDLE REGULAR LEAP YEARS CAIE T3,3 ;SEE IF THIS IS LEAP YEAR MOVEI P1,0 ;NO--WIPE OUT ADDITIVE ADDI T4,<1964-1859>*365+<1964-1859>/4+<31-18>+31(T2) ;T4=DAYS BEFORE JAN 1,1964 +SINCE JAN 1 ; +ALLOWANCE FOR ALL LEAP YEARS SINCE 64 MOVE T2,T1 ;RESTORE YEARS SINCE 1964 IMULI T2,365 ;DAYS SINCE 1964 ADD T4,T2 ;T4=DAYS EXCEPT FOR 100 YR. FUDGE HRREI T2,64-100-1(T1) ;T2=YEARS SINCE 2001 JUMPLE T2,GETNW1 ;ALL DONE IF NOT YET 2001 IDIVI T2,100 ;GET CENTURIES SINCE 2001 SUB T4,T2 ;ALLOW FOR LOST LEAP YEARS CAIE T3,99 ;SEE IF THIS IS A LOST L.Y. GETNW1: ADD T4,P1 ;ALLOW FOR LEAP YEAR THIS YEAR CAILE T4,^O377777 ;SEE IF TOO BIG GETNW2: SETOM T4 ;YES--SET -1 POP P,T1 ;GET MILLISEC TIME MOVEI T2,0 ;CLEAR OTHER HALF ASHC T1,-17 ;POSITION DIV T1,[24*60*60*1000] ;CONVERT TO 1/2**18 DAYS HRL T1,T4 ;INCLUDE DATE MOVE T3,T1 ;DEC VERSION RETURNS NOW, DATE,,TIME IN T1 ;RIPOFF NEEDS IT IN T3.. POPJ P, ;RETURN ;UNDER RADIX 10 **** NOTE WELL **** .MNTAB: EXP 0,31,59,90,120,151,181,212,243,273,304,334,365 RADIX 8 SUBTTL Input routines for command scanner ; ; ; RDATOM reads one command name of any type and returns it in AC 'M'. ; AC 'CH' returns with the next char after the atom, i.e., ; the break character. AC 'P4' returns the arg type, i.e.: ; $CMBRK==0 ; No args read (first char scanned was a break char) $CMBLK==1 ; M is a block argument $CMFIL==2 ; M is a file name RDATOM: SETZB P4,M ; Start with no arg type, no arg TXZ F,.LBS ILDB CH,CMDB ; Get a char from CMD string CAIN CH,"^" JRST RDXCNG ; ^D or ^O sets radix CAIN CH,"#" JRST CLUS ; # means clusters follow CAIN CH,"$" JRST RDATM4 ; $ means octal file name CAIN CH,"'" JRST SIXBRD ; Single quote means SIXBIT CAIN CH,"""" JRST ASCIRD ; Double quote reads ASCII name CAIL CH,"0" ; Between 0-9? CAILE CH,"9" JRST RDATM3 ; No. Must be file name IBP CMDB ; Yes. Must back up byte ptr IBP CMDB ; So RDNUMR reads whole thing IBP CMDB IBP CMDB SOS CMDB ; Really do need DBP (Dec. Byt. Ptr.) instn JRST BLKS ; and go read block number RDWORD: SETZB P4,M ; Alternate entry to always read name RDATM4: ILDB CH,CMDB ; Name is SIXBIT (even though numeric) RDATM3: MOVEI P4,$CMFIL ; Must be SIXBIT file name MOVE T,[POINT 6,M] RDATM1: CAIL CH,"A" ; File names are alphabetic CAILE CH,"Z" SKIPA JRST RDATM2 CAIN CH,"*" ; or stars JRST RDATM2 CAIL CH,"0" ; or numbers CAILE CH,"9" POPJ P, ; None of these, done. RDATM2: TRC CH,40 ; SIXBITize it TLNE T,770000 IDPB CH,T ILDB CH,CMDB ; and get next char JRST RDATM1 ; Here on up-arrow, change radix RDXCNG: ILDB CH,CMDB ; Get next character SETZ T, CAIN CH,"D" ; Was it ^D? MOVEI T,^D10 ; Yes, set radix CAIN CH,"O" ; How 'bout ^O? MOVEI T,^D8 ; Use appropriate radix CAIN CH,"B" ; Last chance is ^B MOVEI T,2 ; Yes, use 2 as radix JUMPE T,CMDERR ; If none of the above, command error MOVEM T,RADIX ; Save for posterity PUSH P,[RDXCN2] ; Return here after reading number MOVE T1,CMDB ; Get command string byte pointer ILDB CH,T1 ; Lookahead one character CAIE CH,"#" ; Start of cluster arg? JRST RDXCN1 ; No MOVEM T1,CMDB ; Advance pointer across # TXO F,.LBS ; Flag cluster argument RDXCN1: MOVE T1,CMDB ; Get possibly changed pointer back ILDB CH,T1 ; Get next character CAIL CH,"0" ; Make sure a number is next CAILE CH,"0"-1(T) ; (of the correct radix) JRST CMDERR ; Nope, error JRST BLKS ; Go read it, return at RDXCN2 RDXCN2: MOVI ^D8,RADIX ; Restore radix POPJ P, ; and return ; Here if block arg indicated (numeric or preceeding #) CLUS: TXO F,.LBS ; Tell SCAN we saw pound sign BLKS: MOVEI P4,$CMBLK ; Indicate block arg PJRST RDNUMR ; and go read a number ; Subroutine to read a number. May be half word octal delimited by comma, ; May contain arithmetic operators +-*' (with no imbedded spaces and ; please no parenthetical expressions!) RDNUMR: MOVE T,CMDB ILDB CH,T CAIE CH,"*" ; See if first char is star JRST RDNUM1 IBP CMDB ; Yes. Inc past it since a lone ILDB CH,CMDB ; star means 'ALL' , not multiplication! SKIPA M,[EXP 400000] ; and flag star in answer RDNUM1: PUSHJ P,NUMIN ; Go read a number CAIE CH,"," ; End in a comma? POPJ P, ; No. done HRLZM M,N ; Yes. save this half of number MOVE T,CMDB ; Test again for lone star/other comma ILDB CH,T CAIE CH,"," ; Have two commas between halfwords? JRST RDNUM3 ; Nope ILDB CH,T ; Get next character to test IBP CMDB ; and adjust CMD string BP also RDNUM3: CAIE CH,"*" JRST RDNUM2 IBP CMDB ILDB CH,CMDB SKIPA M,[EXP 400000] RDNUM2: PUSHJ P,NUMIN HLL M,N ; Retrieve first half of number POPJ P, ; and thats all.. ; Here to read in a simple little number NUMIN: SETZM NUMB ; Start with no number SETZM TERMCH ; and no preceeding character MOVE N1,RADIX ; and get current radix NUMIN0: SETZ M, ; Here for next number NUMINL: ILDB CH,CMDB ; Read a digit CAIL CH,"0" ; Or is it a digit? CAILE CH,"0"-1(N1) ; That's hairy JRST NUMIN1 ; On the other hand, thats not a digit. IMULI M,(N1) ; Digit. Increase running sum radix-fold ADDI M,-"0"(CH) ; Add in this newest digit JRST NUMINL ; Loop for remaining digits. NUMIN1: EXCH CH,TERMCH ; Get term char of last number CAIE CH,"+" ; Add?? JRST NUMIN2 NUMIN5: ADDM M,NUMB JRST NUMIN9 NUMIN2: CAIE CH,"-" ; Subtract? JRST NUMIN3 SUBM M,NUMB MOVNS NUMB JRST NUMIN9 NUMIN3: CAIE CH,"*" ; Multiply? JRST NUMIN4 IMULM M,NUMB JRST NUMIN9 NUMIN4: CAIE CH,"'" ; Divide? JRST NUMIN5 ;NO NONE OF THESE.. EXCH M,NUMB IDIVM M,NUMB NUMIN9: MOVE CH,TERMCH CAIE CH,"+" CAIN CH,"-" JRST NUMIN0 CAIE CH,"*" CAIN CH,"'" JRST NUMIN0 MOVE M,NUMB ; All done. make M=number POPJ P, ; Here to read SIXBIT and ASCII names between delimiters SIXBRD: SETZ M, ; Start with no name ILDB P1,CMDB ; Read the delimiter MOVE T,[POINT 6,M] ; SIXBIT pointer MOVEI T1,770000 ; Non-zero bits in a SIXBIT pointer ANYBRD: MOVEI P4,$CMFIL ; Flag this as a name ILDB CH,CMDB ; Get next char CAIL CH,40 CAIL CH,175 JRST CMDERR ; Can not be a line delimiter! CAIN CH,(P1) ; Repeat of first delimiter yet? JRST RDPOPJ ; Shoor'nuf CAIN T1,770000 ; Processing ASCII or SIXBIT? TRC CH,40 ; SIXBIT.... TLNE T,(T1) ; Reached end of word yet? IDPB CH,T ; No. Put in this char JRST ANYBRD+1 ; and continue ASCIRD: ILDB P1,CMDB ; Read ASCII delimiter MOVE T,[POINT 7,M] ; ASCII pointer MOVEI T1,760000 ; Non-zero ASCII ptr bits JRST ANYBRD RDPOPJ: ILDB CH,CMDB ; Read char after last delimiter POPJ P, ; and ret it ; Routine to get the startup option from the user. ; Returns CPOPJ always with the startup option in ST$OPT. STUERR: MOVEI M,[ASCIZ/Quick, Long, Help /] PUSHJ P,MSGTTY ; Message to type on error STRTUP: MOVEI M,[ASCIZ/Startup option: /] PUSHJ P,MSGTTY ; Ask the user OUTPUT CMD, ; Make sure he sees it PUSHJ P,GETCMD ; Read the option into CMDBUF PUSHJ P,RDWORD ; Get the answer in M MOVE T,[-STULEN,,STUTBL] ; Get AOBJN pointer to table JUMPN CH,STUERR ; Terminating char better be a break SKIPE M ; Value better be non-null PUSHJ P,FNDMAT ; It does, go find a match JRST STUERR ; Bad option PJRST @STUDSP(T) ; Go process it ; ; Here for Quick and Long options. Store value and return ; STUQUI: SKIPA T,[$OPQUI] ; Get code for Quick option and skip STULON: MOVEI T,$OPLON ; Same for Long option MOVEM T,ST$OPT ; Save for later POPJ P, ; and return ; ; Here for Help option. Give more detailed help message ; STUHEL: MOVEI M,[ASCIZ/ Quick - Do not ask about off-line devices Long - Full startup dialog Help - Type this text /] PUSHJ P,MSGTTY ; Tell user PJRST STRTUP ; and try again ; ; Generate the tables of correct responses. STUTBL contains ; the SIXBIT names of the valid options as defined by the ; OPTIONS macro. STUDSP contains the corresponding dispatch ; addresses for these options. ; DEFINE OPTIONS, < X QUICK X LONG X HELP > DEFINE X (OPT), < $OP'OPT==.-STUTBL SIXBIT/OPT/ > STUTBL: OPTIONS STULEN==.-STUTBL DEFINE X (OPT), < EXP STU'OPT > STUDSP: OPTIONS ; Routine to find a match in a table of SIXBIT names. ; Originally stolen from COMCON. ; Call with T = AOBJN pointer to table, M = SIXBIT name to match ; Returns CPOPJ if no (or ambiguous) match ; CPOPJ1 for unique match with T = index in table FNDMAT: MOVN T1,M ; Find the rightmost AND T1,M ; non-zero bit in the name JFFO T1,.+1 ; and its cardinality IDIVI T2,6 ; Find where in SIXBIT byte this bit is LSH T1,-5(T3) ; Right-justify the bit within the byte SOJ T1, ; Make mask of trailing blanks SETZB T4,T2 ; Initialize match pointer and count MOVE T3,T ; Save pointer to table FNDMT2: MOVE N,(T) ; Get next candidate XOR N,M ; Compare with one user gave JUMPE N,FNDMT4 ; Jump if exact match ANDCM N,T1 ; Mask table entry JUMPN N,FNDMT3 ; No partial match either MOVE T4,T ; Partial match--save pointer MOVEI T2,1(T2) ; Count partial matches FNDMT3: AOBJN T,FNDMT2 ; Loop for all entries MOVE T,T4 ; Restore address of possible match SOJN T2,CPOPJ ; More than one means error FNDMT4: SUB T,T3 ; Compute table index of match TLZ T,-1 ; Clear junk JRST CPOPJ1 ; and return success ; Subroutine to input a date,,time word from the cmd TTY REPEAT LOGIC,< Type-in format is : Date , Time or Time , Date Where date = dd-mmm-yy or dd-mmm-yyyy and time = hh:mm:ss or hh:mm Blanks or tabs may occur anywhere, comma must seperate the two. Also, either time or date or both may be left out, zero returned Returns T3=Universal date,,time word > GTDT5: POP P,RADIX ; Restore original radix MOVEI M,[ASCIZ! %Type date as dd-mmm-yy, time as hh:mm or hh:mm:ss seperated by a comma !] PUSHJ P,MSGTTY GTDATE: PUSHJ P,GETCMD ; Get the command string PUSH P,RADIX ; Save old radix MOVI ^D10,RADIX ; Implied radix ten here SETZB P1,TTIME ; Clear junk SETZM TDATE ; and lets read some stuff.... GTDT4: PUSHJ P,GTDNUM ; Read a number CAIN CH,":" ; End in a colon? JRST GTDT10 ; Yes. Go process time CAIN CH,"-" ; How about a slash? JRST GTDT20 ; Go process. JUMPN CH,GTDT5 ; Anything else is err, unless EOL ; Here on EOL. Done MOVE T1,TTIME ; Get time IMULI T1,^D1000 ; in milliseconds MOVE T2,TDATE PUSHJ P,.CNVDT ; Convert to universal SKIPN TDATE ; Special kludge ** ; Did he give me a zero date?? HRRZS T3 ; Yes. So return zero date ; Note- He can never do ; a /IT before Jan-1-64, since that is zero POP P,RADIX ; Restore old radix and POPJ P, ; return ; Here to process time GTDT10: IMULI M,^D3600 ; Convert hours to seconds MOVE P1,M ; Store in P1 PUSHJ P,GTDNUM ; Read minites IMULI M,^D60 ; Convert to seconds ADD P1,M ; Add into running total CAIN CH,"," ; Done here? JRST GTDT11 ; Yes. Go process more JUMPE CH,GTDT11 CAIE CH,":" ; More to come? JRST GTDT5 ; No. Illegal PUSHJ P,GTDNUM ; Read seconds ADD P1,M ; Add them in there GTDT11: MOVEM P1,TTIME ; Store time JRST GTDT4 ; and loop ; Here to process date type-in GTDT20: CAILE M,^D31 ; Day can't be > 31 JRST GTDT5 ; Else it's an error MOVEI P1,-1(M) ; Day-1 to P1 SETZM N ; Setup to accumulate month GTDT30: ILDB N1,CMDB ; Get next char JUMPE N1,GTDT5 ; EOL is illegal here CAIN N1,"-" ; Find end of month? JRST GTDT40 ; Yes ROT N1,-7 ; Left justify character LSHC N,7 ; and accumulate it in N JRST GTDT30 ; Loop for more GTDT40: LSH N,7+1 ; Make it 0MMM0 TDO N,[BYTE (7)"-",0," "," ","-"] ; Make it -Mmm- HRLZI T1,-^D12 ; Make AOBJN pointer for MONTAB GTDT50: CAME N,MONTAB(T1) ; Find match in MONTAB? AOBJN T1,GTDT50 ; No, try next TLZN T1,-1 ; Clear LH and check for match JRST GTDT5 ; No match, error IMULI T1,^D31 ; T1=(mon-1)*31 ADD P1,T1 ; P1=(mon-1)*31+day-1 PUSHJ P,GTDNUM ; Get year CAIG M,^D99 ; Allow 1978 ADDI M,^D1900 ; Convert from 78 to 1978 SUBI M,^D1964 ; Subtract zero year IMULI M,^D31*^D12 ; M=(year-1964)*31*12 ADD P1,M ; P1=((yy-1964)*12+(mm-1))*31+dd-1 MOVEM P1,TDATE ; Save in core JRST GTDT4 ; and see what's left ; Here to read a decimal number from the command string for date/time ; Returns number in M, terminator in CH GTDNUM: SETZ M, ; Clear number GTDNM1: ILDB CH,CMDB ; Get next char from command string CAIL CH,"0" ; Is it a digit? CAILE CH,"9" POPJ P, ; No, that's it IMULI M,^D10 ; Make room for next digit ADDI M,-"0"(CH) ; Convert to binary and add to total JRST GTDNM1 ; Loop for more ;ROUTINE TO PRINT THE EXACT TIME NOW.. NOW: MSTIME T1, ;TIME IN MILLISECONDS IDIVI T1,^D60000 MOVE T3,T2 IDIVI T3,^D1000 ;SECONDS IN T3 IDIVI T1,^D60 ;HOURS IN T1, MINITES IN T2 MOVNI T4,2 SKIPA CH,[40] NOWLUP: MOVEI CH,":" PUSHJ P,W.LST MOVEI T,2 MOVE N,T3(T4) ;GETS HOURS, THEN MIN, THE SECONDS PUSHJ P,DECZRO AOJLE T4,NOWLUP PUSHJ P,SPC2 DATE T1, ;GET DATE AND HIT PRDT1 JRST PRDT1 ;GO PRINT IT. ;ROUTINE TO PRINT THE DATE, DATE IN T3 IN UNIVERSAL STANDARD PRDATE: JSP M,SAVE3 ;SAVE P1 PUSHJ P,.CNTDT ;GET T1=MS TIME, T2=DATE IN 15 BIT MOVE T1,T2 ;15 BIT DATE TO T1 PRDT1: IDIVI T1,^D31 MOVEI N,1(T2) ;DAY MOVEI T,2 PUSHJ P,DECZRO IDIVI T1,^D12 MOVE T2,MONTAB(T2) ;MONTH SETZ T3, MOVEI M,T2 PUSHJ P,MSG MOVEI N,^D64(T1) ;YEAR PUSHJ P,DECPR1 ; PJRST SPC2 ;AND TWO SPACES MONTAB: DEFINE MONMAC(X) > MONMAC ; Routine to print the time. Call with universal date/time ; in T3. PRTIME prints as hh:mm:ss, PRTIM1 prints as hhmm PRTIME: TLOA T3,-1 ; Flag entry PRTIM1: TLZ T3,-1 ; Ditto JSP M,SAVE3 ; Get some registers to use HLRE P3,T3 ; Move entry flag to P3 HRRZ P1,T3 ; Move universal time to P1 IMULI P1,^D60*^D60*^D24 ; Convert to seconds HLRZS P1 ; Compute seconds since midnight IDIVI P1,^D60*^D60 ; P1=hours, P2=seconds into hour MOVEI T,2 ; Field width MOVE N,P1 PUSHJ P,DECZRO ; Print hours as two digits SKIPE P3 ; Skip if entry at PRTIM1 PUSHJ P,COLON ; Print a colon MOVE P1,P2 ; Get seconds back IDIVI P1,^D60 ; P1=minutes, P2=seconds MOVEI T,2 ; Field width MOVE N,P1 ; Get minutes PUSHJ P,DECZRO ; Print as two digits SKIPN P3 ; Skip if entry at PRTIME PJRST SPC2 ; End with 2 spaces if entry at PRTIM1 PUSHJ P,COLON ; Print colon MOVEI T,2 ; Field width MOVE N,P2 ; Get seconds PUSHJ P,DECZRO ; Print as two digits PJRST SPC2 ; End with space and return ;HERE TO WRITE TO THE LPT W.LST: TXNE F,F.TTY!F.TTY2 ;TTY OUTPUT INSTEAD? JRST W.CMD ;YES. WRITE TTY SKIPN PAGES ;FIRST PAGE?? JRST W.LST0 ;YES. DO SPECIAL THINGS CAIN CH,.CHLFD ;THIS A LINE FEED? JRST .+4 ;YES.GO FIX LINE COUNT CAIE CH,.CHFFD ;HOW ABOUT A FORM FEED? JRST W.LST2 ;NEITHER. JUST GO TYPE IT JRST PHED ;FORM FEED. GO PRINT NEW HEADER AOS CH,LINES ;LINE FEED. INC LINE COUNT CAILE CH,PAGSIZ ;DO A FREE FF YET?? JRST PHED ;YES. MOVEI CH,.CHLFD PUSHJ P,W.LST2 ;NO. JUST TYPE A LF MOVEI CH,.CHTAB ;AND A TAB TXZN F,F.ERRM ;UNLESS THIS IS AN ERROR MESSAGE JRST W.LST2 POPJ P, ;IN WHICH CASE WE IGNORE THE TAB PHED: MOVEM F,PHEDF ;SAVE FLAGS SO CAN TEST F.ERRM LATER PUSHJ P,SAVALL ;SAVE AC'S MOVEI CH,.CHFFD PUSHJ P,W.LST2 ;BEGIN WITH A FORM FEED SETZM LINES ;RESET LINE COUNT SKIPN PAGES SETOM PAGES ;TO STOP INFINITE LOOP AT W.LST+2 MOVEI M,IDRIP PUSHJ P,EMSG ;RIPOFF V LDB N,VERPTR PUSHJ P,OCTPRT ;VERSION NUMBER PUSHJ P,LPAR HRRZ N,.JBVER PUSHJ P,OCTPRT ;EDIT NUMBER MOVEI M,[ASCIZ/) /] PUSHJ P,MSG PUSHJ P,NOW ;PRINT TIME AND DATE MOVEI M,[ASCIZ/ */] PUSHJ P,MSG MOVE M,[POINT 7,CMDBUF] MOVEI P1,MAXCMD PHED1: ILDB CH,M ;GET A CMD STRING CHAR JUMPE CH,PHED2 SOJLE P1,PHED3 ;TO MANY CHARS, IGNORE REST PUSHJ P,W.LST2 ;PRINT IT JRST PHED1 ;LOOP FOR ALL CHARS PHED2: MOVEI CH," " PUSHJ P,W.LST2 SOJG P1,PHED2 PHED3: MOVEI M,[ASCIZ/ Page /] PUSHJ P,MSG AOSG N,PAGES ;NOW GIVE PAGE COUNT AOS N,PAGES PUSHJ P,DECPRT PUSHJ P,CRLF2 MOVE F,PHEDF ;RESTORE ORIGINAL FLAGS PJRST CRLF ;ONE MORE CR BEFORE EXIT (FOR F.ERRM) U(PHEDF) W.LST2: SOSG WH.LST+2 OUTPUT LST,0 IDPB CH,WH.LST+1 POPJ P, W.LST0: PUSH P,CH ;HERE IF VERY FIRST CHAR OUTPUT PUSHJ P,PHED ;SINCE COMMAND STRING. PRINT HEADER POP P,CH CAIE CH,.CHLFD CAIN CH,.CHFFD POPJ P, PJRST W.LST2 ;AND PRINT FIRST CHAR IF NOT LF OR FF ; Routine to read a command from the TTY and store it in CMDBUF. ; Returns CPOPJ always with ASCIZ command in CMDBUF and byte ; pointer to start of command in CMDB. GETCMD: JSP M,SAVE3 ; Get some registers to use MOVE P1,[POINT 7,CMDBUF] ; Get byte pointer to buffer MOVEM P1,CMDB ; Save for calling routine MOVEI P2,MAXCMD ; Max # of chars to input GTCMD1: PUSHJ P,R.CMD ; Read a character CAIE CH,.CHCNZ ; [075] ^Z typed? JRST GTCMD4 ; [075] No. CLOSE CMD,CL.OUT ; [075] Close input side of TTY MOVEI CH,0 ; [075] Change character to a null PUSH P,[GTCMD4] ; [075] Push return address from CZEXIT PJRST CZEXIT ; [075] and go simulate a ^C GTCMD4: ; [075] CAIE CH,.CHTAB ; Ignore tabs and spaces CAIN CH," " JRST GTCMD1 ; [075] CAIL CH," " ; Line delimeter? CAIL CH,.CHALT JRST GTCMD3 ; Yes, done GTCMD2: SOJLE P2,GTCMD1 ; Too many chars, ignore the rest IDPB CH,P1 ; Put character into CMDBUF JRST GTCMD1 ; and continue scan GTCMD3: SETZ CH, ; Make sure parser finds the end of IDPB CH,P1 ; the string IDPB CH,P1 POPJ P, ;GET A CMD STRING CHAR R.CMD: SOSG RH.CMD+2 INPUT CMD, ILDB CH,RH.CMD+1 JUMPE CH,R.CMD ;IGNORE NULLS CAIE CH,.CHDEL ;DELETE, AND CAIN CH,.CHCRT ;CARRIAGE RETURN JRST R.CMD CAIL CH,.CHALT ;MAKE ALL ALTIMODES STANDARD MOVEI CH,.CHESC CAIL CH,"A"+40 ;AND CONVERT LOWER TO UPPER CASE TRZ CH,40 POPJ P, ;HERE TO WRITE A CHARACTER TO THE TELETYPE W.CMD: SOSG WH.CMD+2 OUTPUT CMD, IDPB CH,WH.CMD+1 CAIG CH,.CHCRT ;IF CARRIAGE RET OR LINE FEED, OUTPUT CMD, ;FORCE OUTPUT POPJ P, ;TEMPORY STORAGE PDP: IOWD PDLSIZ,PLIST VERPTR: POINT 9,.JBVER,11 ;POINTER TO MAJOR VERSION IN .JBVER ONEONE: 1,,1 ;A COMMON CONSTANT.. BIGNUM: EXP -1_<-1> ;THE LARGEST POSITIVE 36 BIT NUMBER. IDRIP: ASCIZ/Ripoff V./ HED1: ASCIZ /File Ext Log block Access Creation Prv Mode Words Blocks Err Number Name 1st RIB Date Time Date Written Written Alloc Bits Ptrs/ BLKMSG: ASCIZ / blocks/ UBLKMG: ASCIZ / total disk space allocated to this user. / AVEMSG: ASCIZ / Average file size for / AVEMS1: ASCIZ / files = / UBLK1: ASCIZ / blocks / UHED: ASCIZ / Unit Unit ID Log unit in STR / SATMSG: ASCIZ / SAT block / FREMSG: ASCIZ / free blocks left in this SAT block/ TOTMSG: ASCIZ / total disk space remaining. / TBLKMG: ASCIZ / total disk space used by all user's files. / BATHED: ASCIZ /BAT block for unit / WASMSG: ASCIZ/ Blocks wasted in totally unwritten yet allocated blocks = / MSGRIB: ASCIZ/ Number of blocks used for RIBS = / NULMSG: ASCIZ/ Number of null UFDs = / MISMSG: ASCIZ / Discrepancies in number of free blocks Computed SAT blocks DSKCHR / ERRHED: ASCIZ / Number of files with each type of error Hard Hard Soft Damage Backup Crash write read check assess / HISHED: ASCIZ !File size and RIB length Histogram N Files Rib ptrs ! RIBHED: ASCIZ/ Retrieval pointers: Pointer Block in # of Unit Checksum unit STR blocks / DIRPM: ASCIZ/ File Ext Block in Unit Name unit STR # / XLIST ;LITERALS UNDER XLIST LIT VAR LIST SUBTTL Low segment storage definitions REPEAT LOGIC,< ;****************** Note ***************** All locations from ZROBEG through ZROEND are zeroed on every major restart (i.e., all low segment cleared on 'START' or 'RUN' command). All locations from CMDBEG through ZROEND are zeroed on every command string (a star typed). > U(ZROBEG) ; ********* From here to ZROEND cleared on START U(MFDPPN) ; Five PPNs from GETTAB U(SYSPPN) U(FSFPPN) U(HELPPN) U(QUEPPN) U(CRSPPN) ; Crash PPN [10,1] VIPS==MFDPPN ; First GETTAB PPN needed U(WMASK) ; Search mask for /W code U(WWORD) ; Search word for /W code U(QUESTR) ; Queing STR U(STNPRT) ; System standard file protection U(UFDPRT) ; Standard UFD protection U(DEVOPR) ; SIXBIT name of OPR TTY U(%LOCK) ; -1 if job locked in core U(CPUXX) ; 0=KA,1=KI,2=KL processor type. U(COREXX) ; Number of words per core unit, ie, 512 or 1024 on KA. U(STRTAB) ; Ptr to table of structures in system U(UNIDDB) ; Initial ptr to UDB tables U(RADIX) ; Current input radix UU(PLIST,PDLSIZ) ; Pushdown stack. U(EBUF) ; Pointer to disk read/edit/write buffer U(ESTR) ; STR above block read in by U(EBLK) ; Block in STR of above block U(EWORD) ; Last word diddled in /EC or /ET U(%FTSFD) ; =-1 if monitor has SFD'S, 0 otherwise U(LSTDEV) ; Physical name of list device UU(IOW,2) ; IOWD to BUF kept here ZERO=IOW+1 ; Always will be a zero here U(CMDBEG) ; ********* From here to ZROEND zeroed every '*' U(.SVFF) ; For saving .JBFF U(GOTWRD) ; Non-zero if word specified in /ET or /EC U(CMDLVL) ; Deepest level of path specified in CMD string U(CURLVL) ; Current level of SFD nesting U(PTHFLG) ; Non-zero if path specified in cmd UU(SFDFLG,SFDLVL+1) ; If SFDFLG(I) is non-zero, a star was ; seen in the command string at level I UU(MATFLG,SFDLVL+1) ; If MATFLG(I) is non-zero, files in the directory ; at level I may be matched, i.e., the path at ; level I matches the command string and allows ; files to be matched within the directory UU(TMPPTH,.PTPPN+1+SFDLVL+1) ; Temporary path specs built here U(USRSTR) ; Structure U(USRNAM) ; File name U(USREXT) ; File extension U(USRPPN) ; and PPN UU(USRPTH,.PTPPN+1+SFDLVL+1) ; Path specification U(USRCFP) ; CFP to file U(UFDCFP) ; CFP to file's UFD U(TTYNAM) ; The name typed in by the user U(TTYEXT) ; The actual chars typed in for ext U(TTYPPN) UU(TTYPTH,.PTPPN+1+SFDLVL+1) ; Path specification U(TTYSTR) U(TTYTYP) U(TTYDDB) U(AUXDEV) ; Scratch output device U(AUXNAM) ; Scratch file name U(AUXEXT) ;.. U(AUXPPN) ;.. UU(AUXPTH,.PTPPN+1+SFDLVL+1) ; Path specification U(AUXCHR) ; DEVCHR on aux channel U(AUXTRY) ; Amount of buffer space to try for by AUXALC U(AUXSIZ) ; Size of aux buffers (DEVSIZ UUO) UU(AUXOB,3) UU(AUXIB,3) U(UFILCT) ; User file count U(UBLKCT) ; User block count U(UFDCNT) ; Total blocks devoted to UFDs U(MFDCT) ; Total number of files in MFDPPN U(NULUFD) ; Total number of null UFDs U(TOTDSK) ; Total free blocks according to DSKCHR UUO U(WASTEB) ; Wasted blocks U(TBLKCT) ; Total # of blocks allocated to users on STR U(TFILCT) ; Total # of files on STR UU(FERR,6) ; Counters for hard file errors UU(HISTO,TOPHIS+2); Histogram counters UU(HISTOR,TOPHIS+2); Histogram for # of RIB ptrs U(TOTSAT) ; Total free blocks according to SAT table U(CTYPE) ; Current controller type U(CUNIT) ; Current unit in controller UU(STRUNI,MAXUNI+1) ; Table of unit UDB address in STR U(SETBLK) ; Used to save block arguments U(HIGHU) ; Highest unit in STR U(STRBPU) ; Highest BLKUNI in str U(TEMP) ; Extremely tempory storage U(TEMP1) ; IBID U(TEMP2) ;.. U(TEMP3) ;.. UU(LHEAD,2) ; List headers for /I code U(STRGRP) ; First location transferred from UNIDDB's at init time U(STRBSC) ; Blocks/supercluster U(STRSCU) ; Superclusters/unit U(STRCNP) ; HOMCNP U(STRCKP) ; HOMCKP U(STRCLP) ; HOMCLP U(STRBPC) ; HOMBPC U(STRSIZ) ; Total blocks on STR U(STRHGH) ; Highest logical block on STR +1 U(CLSCNT) ; Cluster count used at NOCHEK+3 U(NUMB) ; Numbers built here in RDNUMR U(TERMCH) ; Terminating character U(STRFLG) ; Flag counting passes through NXTSTR U(PASS) ; Pass counter for /V code U(TTIME) ; Time for GTDATE routine U(TDATE) ; Date for GTDATE routine U(AFTER) ; In /I, only get file after this date U(BEFORE) ; and before this one... U(OTHERK) ; Flag used by dsklst BAT block processor U(WENABLE) ; Write enables units for BLKWRT for debugging U(NOIO) ; -1 tells BLKRED/WRT not to do I/O. U(SAVECH) ; BUFSAV saves AC CH here U(ERRFL) ; -1 suppresses extended errors in DEVERR. U(SATFLG) ; At SEARCH, if -1, ignore blocks set in SATs U(WTFLAG) ; 0=reading,-1=writing at RD/WT-SAT UU(CMDBUF,/5) ; ASCII CMD string kept here U(CMDB) ; Byte pointer to above CMD string U(PAGES) ; Page count U(LINES) ; Line count U(BUFHED) ; Must be BUF-1. Is a word before BUF... UU(BUF,BLKSIZ) ; Jack-of-all-trades buffer BUFIOW=BUF-1 ; For DDT in IOWDS to BUF.. UU(TIOW,2) ; Tempory IOWD's kept here U(BARG1) ; Blocksize argument U(BARG2) ; Blocksize upper limit. U(BARG3) ; Relative block arg U(BARGFL) ; Bit 35-n=1 if barg'N is clusters, not blocks U(DSKPTR) ; Pointer to DSKSAT U(OURPTR) ; Ptr to OURSAT U(TRBPTR) ; Ptr to TRBSAT DEFINE UUU(NAME,LEN) < NAME==CRBSIZ CRBSIZ==LEN+CRBSIZ > CRBSIZ==0 BLKFIR==0 ; First entry in core block to zero on INBUF UUU(XIOWD,1) ; IOWD to datbuf UUU(WDCNT,1) ; Word count of data left in DATBUF UUU(BLKCNT,1) ; # of blocks left this group UUU(FILEN,1) ; # of blocks left in file. decremented to find eof UUU(THISBL,1) ; Block on unit we're reading now UUU(THISU,1) ; Unit for above block UUU(DATBUF,BLKSIZ) ; Buffer for data to be transferred to UUU(DATPTR,1) ; Pointer to above data BLKEND==DATPTR ; Zero block on INBUF to here only UUU(SAVRIB,BLKSIZ-RIBENT) ; RIB copyied into here UUU(FNAME,1) ; File name looked up on channel UUU(FEXT,1) ; Extension UUU(RIBLBN,1) ; Logical block in STR of first RIB UUU(FPATH,.PTPPN+1+SFDLVL+1) ; Path of file looked up on channel FPPN==FPATH+.PTPPN ; Allow references to the PPN UUU(FCFP,1) ; CFP of this SFD/UFD UUU(RIBFLG,1) ; Flag says reading first RIB UUU(FILSTS,1) ; Copy of RIBSTS word in RIB UUU(SAVXRA,1) ; Copy of RIBXRA, extended RIB address UUU(IOSTS,1) ; LH=internal bits, RH=GETSTS word ; is contained UU(MFD,CRBSIZ) ; Core block for MFD UU(UFD,CRBSIZ) ; UFD, UU(DSK,CRBSIZ) ; and disk IFG SFDLVL, < DEFINE X (N), < UU(SFD'N,CRBSIZ) > I=1 REPEAT SFDLVL, < X (\I) I=I+1 > > U(ZROEND) ; ******** Last location zeroed ******** ;*********** From here on, locations never zeroed.. UU(INTBLK,.ERCCL+1) ; ^C intercept block U(OURPPN) ; PPN running RIPOFF now. U(%SUSET) ; -1 if can do SUSET. UUO. 0 if Super USETI/O U(.JBMAX) ; Cormax minus hiseg (amount of core free to lowseg) U(ST$OPT) ; Startup option ($OPQUI, $OPLON) UU(RH.CMD,HEDNUM) ; TTY and LPT buffer headers UU(WH.CMD,HEDNUM) UU(WH.LST,HEDNUM) U(LOWSIZ) ; Highest loc in low segment RIPEND: Z ; Th..th..th..that's all folks IFN PURESW,< RELOC 0 ; Must have all UU(DATA) begin in low seg BLOCK LOWSIZ-140 ; Give it all room.. > END RIPOFF