.MCALL .MODULE .MODULE DUPSQU,VERSION=07,COMMENT=,IDENT=NO ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. ; Edit History: ; ; 001 28-Jan-80 11:00 Guldenschuh, Chuck cpg [240,148] ; Correct "Volume not RT-11 format" problem ; (001) ; 002 11-Nov-80 11:37 AM Fingerhut, David [240,134] ; SQUEEZE creates entries of length 0 before .BADs ; (002) ; 003 10-Nov-81 04:11 PM David Fingerhut [40,134] ; Changes for RTEM ; (003) ; ; 20-JULY-84 George Thissell ; Fix SPFUN vs. READ/WRITE problem ; ; 006 06-Nov-1990 JFW ; bracket error messages with ;+/;ERROR/.../;- .ENABL LC,GBL .SBTTL MACRO definitions .IIF NDF MDUP, MDUP = 0 ;Default to no MDUP .IIF NDF M$UPD, M$UPD = 0 ;Default to no MDUP Update .IIF NDF SDC, SDC = 0 ;Default to no SDCOPY .MACRO READSG SEG,BUF .IIF NB , MOV SEG,R2 .IIF NB , MOV BUF,DIOBUF CALL RDSEG .ENDM READSG .MACRO WRITSG SEG,BUF .IIF NB , MOV SEG,R2 .IIF NB , MOV BUF,DIOBUF CALL WTSEG .ENDM WRITSG .MACRO ERRMSG NAME,TEXT DS NAME,BYTE .PSECT .LIBD. EM.'NAME: .ASCII \TEXT\<200> .PSECT .LIBP. .WORD EM.'NAME .ENDM ERRMSG .MACRO MSGLST NAME .DSECT ...ERS,GLOBAL=NO .PSECT .LIBP. NAME: .WORD ..MAX. .ENDM MSGLST .MACRO MSGEND DS ..MAX.,BYTE .ENDM MSGEND .SBTTL PSECT definitions PSECT ...ERS ; ;001 PSECT IMPURE ;Impure data PSECT .LIBD. ;Library data (error messages) PSECT .LIBP. ;Library pointers (error messages) PSECT PUREB ;[byte] Pure data PSECT PURE ;Pure data PSECT SQUEEZ ;Code psect PSECT PATCH ;Patch psect .BLKW 32. .SBTTL Error Messages ;+ ;ERROR MSGLST OERTAB ERRMSG NSF, ERRMSG UIV, MSGEND ;- .SBTTL Impure data PSECT IMPURE XDR1SP: .WORD 0 ;saved SP to avoid messy cleanup in EXTDR1 NOABRT: .WORD 0 ;Abortable flag. 0 => can abort OUTER: .WORD 0 ;Output error handler address RELCOR: .WORD 0 ;-> directory buffers SAVENT: .WORD 0 ;Relative address of current entry. SAVESZ: .WORD 0 ;Size of empty area we're using up ;Error message area block OEAREA: .BYTE 0 ; Error code byte .BYTE 0 ; Error level/return flag .WORD ERRPRE ; -> Error message prefix .WORD ERRLEV ; -> Error level byte .WORD OERTAB ; -> Error message offset table .WORD 0 ; -> File name block .WORD ABORT ; -> Abort return SYS: .RAD50 \SY \ ;Device name for system volume check SYS1: .WORD 0 ;Filename and real device name (eventually) DIOARA: .BYTE ICHAN ; Channel .BYTE 0 ; Function code .WORD 0 ; Block number DIOBUF: .WORD 0 ; Buffer .WORD SEGSIZ ; Word count .WORD 0 ; Completion routine PSEG: .BLKB 32. ; ;Fake file for .BAD creation FILBAD: .WORD DS.PRM ;Status is permanent .RAD50 \FILE BAD\ ;Filename is FILE.BAD .WORD 0 ;File size (filled in at runtime) .WORD 0 ;Job/Channel .WORD 0 ;Creation date (filled in at runtime) ;Fake empty entry for SHFFL1 EMPTYF: .WORD DS.EMP ;Status is empty .RAD50 \ EMPTYFIL\ ;Filename is bEMPTY.FIL .WORD 0 ;File size (filled in at runtime) .WORD 0 ;Job/Channel .WORD <14*2000>+<37*40>+33 ;Date ;**-14 .SBTTL RTEM-11 macro definitions ;003 .SBTTL ;003 ;003 .MACRO DEFINE NAME ;003 ..DF.. = 0 ;003 .ENDM DEFINE ;003 ;003 .MACRO DEF NAME,TYPE,SIZE ;003 .IF NB NAME ;003 NAME == ..DF.. ;003 .ENDC ;003 .IF NB TYPE ;003 .IF IDN TYPE, ;003 .IF B SIZE ;003 ..DF.. = ..DF.. + 1 ;003 .IFF ;003 ..DF.. = ..DF.. + SIZE ;003 .ENDC ;003 .IFF ;003 .IF B SIZE ;003 ..DF.. = ..DF.. + 2 ;003 .IFF ;003 ..DF.. = ..DF.. + ;003 .ENDC ;003 .ENDC ;003 .IFF ;003 .IF B SIZE ;003 ..DF.. = ..DF.. + 2 ;003 .IFF ;003 ..DF.. = ..DF.. + ;003 .ENDC ;003 .ENDC ;003 .ENDM DEF ;003 ;**-104 .SBTTL RTEM-11 Virtual System Device Setup Table Definition ;003 ;++ ;003 ; VS$SET ;003 ; DATA STRUCTURE DEFINITION ;003 ; ---- --------- ---------- ;003 ; ;**-5 ; Data in this table gives information about the private, shared, and ;003 ; read/write temporary files. This information is used by the VS ;003 ; (virtual system device) driver to map these three files into a single ;003 ; virtual system device. ;003 ; ;**-10 ; (S) shared (P) private (T) r/w temporary (W) whole VS devi;003 ; ;**-6 ; ;**-1 ; ***********************NOTE****************************** ;003 ; ********* YOU DON'T WANT TO CHANGE THIS TABLE *********** ;003 ; ****** If this changes, you must change RT-11 DUP ****** ;003 ; ****** And you might as well hang it up with TKVSM ****** ;003 ; ** This list IS ORDER DEPENDANT. If the order changes ** ;003 ; *** You MUST RE-LINK RTEMFB.SYS,nnM.SYS,JOAT and FIP *** ;003 ; ********************************************************* ;003 ; ;**-15 ; *** ALSO NOTE *** ;003 ; If you change this table, you must also change the installation routin;003 ; in the virtual system device driver (VS). ;003 ; ;**-1 ;-- ;003 DEFINE ; Define some offsets ;003 DEF VS$SSM ; (S) # directory segments to ma;003 DEF VS$PSM ; (P) # directory segments to ma;003 DEF VS$SDB ; (S) # last directory block ;003 DEF VS$SFW ; (S) # first r/w block ;003 DEF VS$SLW ; (S) # last r/w block ;003 DEF VS$SLB ; (S) # last shared file block ;003 DEF VS$PDB ; (P) # last directory block ;003 DEF VS$PLB ; (P) # last private file block;003 DEF VS$PHO ; (P) # highest open directory s;003 DEF VS$PLU ; (P) private file LUN ;003 DEF VS$SLU ; (S) shared file LUN ;003 DEF VS$TLU ; (T) temporary file LUN ;003 DEF VS$SIZ ; (W) VS device size ;003 DEF VS$BRO ; (W) VS bootstrap read offset;003 DEF VS$PT1 ; (W) ** Patch space ** ;003 DEF VS$PT2 ; (W) " ;003 DEF VS$PT3 ; (W) " ;003 DEF $VSTSZ,, 0 ; Size of VS setup table (bytes);003 ;**-18 .SBTTL ;003 .SBTTL RTEM-11 Data for squeeze for virtual system device ;003 ;003 R50VS0 = ^RVS0 ; Device name to see if squeezing VS0 ;003 ;003 SQUVS0: .WORD 0 ; Squeezing-VS0-as-system-device flag ;003 FSTSEG: .WORD 1 ; No. of first private segment in VS0 ;003 ; (or 1 if not squeezing VS0 as system;003 SHRSIZ: .WORD 0 ; Size of shared file area on the VS ;003 SEG1FG: .WORD 0 ; Flag if segment 1 has been updated ;003 ;003 .SBTTL ;003 .SBTTL PURE Text and data for squeeze ;003 ;003 PSECT PUREB ;003 ;003 .NLIST BEX ;003 MSGSQU: .ASCII \/Squeeze\<200> ;003 .LIST BEX ;003 ;003 PSECT PURE ;003 ;003 AST: .WORD R50AST,0,R50AST ;"*.*" for 2 device squeeze .BAD file se;003 ;003 ASTBAD: .WORD R50AST,0 ;"*.BAD" for 1 device squeeze .BAD file ;003 .RAD50 \BAD\ ;003 DUP: .RAD50 \SY DUP SAV\ ;Our filename ;003 ;003 ;003 ;003 .SBTTL SQUEEZ - Squeeze a device ;003 ;003 ;+ ;**-2 ; SQUEEZ ;003 ; This is the set up code for both the single device and dual device squ;003 ; routines. It allocates the buffers and makes sure the user really wan;003 ; do the squeeze. It also does some checking for things like squeezing ;003 ; while the foreground is loaded. Also sets up parameters if squeezing R;003 ; VS0 system device ;003 ;- ;**-15 ORIGIN SQUEEZ ;003 ;003 .ENABL LSB ;**-25 SQUEEZ:: CLRB SPFUNO ;Clear SPFUN output flag CLRB SPFUNI ;Clear SPFUN input flag BIT #FLG.DV,$OSFLG ;Is this a two device squeeze? ;003 BEQ 1$ ;Branch if not ;003 CMP INFILE,OUTFIL ;Are the devices the same? ;003 BNE 6$ ;Branch if not ;003 BIC #FLG.DV,$OSFLG ;Clear the flag bit ;003 1$: .LOOKUP #IOAREA,#16,#SYS ;Lookup the system device ;003 BCC 4$ ;Branch if no error ;003 ;+ ;ERROR MOV #FE.SYS,R0 ;Oops! Shouldn't happen ;003 ; <-F-System error> ;003 ;- 2$: CLR R3 ;003 ;+ ;ERROR MOV R0,R1 ;Copy error code ;003 .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=NO,FILE=R3 ;**-8 ;- 4$: MOV #16,R0 ;R0 = channel number ;003 MOV #SYS1,R1 ;R1 -> location to store real device nam;003 CALL REALDV ;Convert logical to physical ;003 .PURGE #16 ;Purge the channel ;003 CMP @R1,INFILE ;Same device we're supposed to init? ;003 BNE 6$ ;Branch if not. Do normal message ;003 INC SQUSYS ;Set the squeezing SY: flag ;003 CMP @#$RTEID,#RTE$ID ;Are we running under RTEM ;003 BNE 101$ ; No ;003 CMP INFILE,#R50VS0 ; Yes - are we squeezing VS0? ;003 BNE 101$ ; No ;003 INC SQUVS0 ; Yes - set flag ;003 MOV @#$RTELK,R1 ;Point to monitor linkage table ;003 MOV @R1,R1 ;Point to VS table in monitor (1ST OFFSE;003 MOV VS$SSM(R1),FSTSEG ;Get no. of shared segments ;003 INC FSTSEG ;Make it first private segment no. ;003 MOV VS$SLB(R1),SHRSIZ ;Get last file block in shared file ;003 SUB VS$SDB(R1),SHRSIZ ;Make it size of shared file area ;003 CLR SEG1FG ;Clear segment 1 update flag ;003 101$: .GVAL #IOAREA,#S.CNF1 ;Get the first config word ;003 BIT #C1.FGL,R0 ;Is the foreground loaded? ;003 BEQ 6$ ;Branch if not ;003 ;+ ;ERROR MOV #NSF,R0 ;R0 = error code ;003 MOV R0,R1 ;Copy the error code ;003 .ERR #OEAREA,R1,LEVEL=FATAL,RETURN=NO ;003 ; <-F-Can't Squeeze SY: while foreground loaded> ;003 ;- ;003 6$: .GTCOR # ;Get three directory buffers ;003 BCC 8$ ;Branch if we got it ;003 ;+ ;ERROR 7$: MOV #FE.NOM,R0 ;R0 = error code ;003 ; <-F-Insufficient memory> ;003 BR 2$ ;Go give error ;003 ;- ;003 8$: MOV R0,$DIRBF ;Set pointer to primary directory buffer;003 MOV R0,RELCOR ;Save pointer for release ;003 MOV R0,R5 ;Copy the pointer ;003 ADD #,R0 ;R0 -> secondary directory buffer ;003 MOV R0,$DIRB2 ;Save it ;003 ADD #,R0 ;R0 -> tertiary directory buffer ;003 MOV R0,$DIRB3 ;Save the pointer ;003 9$: .GTCOR # ;Get the .BAD list buffer ;003 BCS 7$ ;Branch on error ;003 ; <-F-Insufficient memory> ;003 CMP (R0)+,(R0)+ ;Leave 1 entry for error recovery ;003 MOV R0,BADLHD ;Save the start address ;003 .GTCOR #-2 ;Get the rest as an I/O buffer ;003 BCS 7$ ;Branch if none! ;003 ; <-F-Insufficient memory> ;003 MOV R0,IBFBEG ;Save the start address ;003 BIC #777,R1 ;Clear out ugly bits ;003 ROR R1 ;Make it words ;003 BEQ 7$ ;Branch if none! ;003 ; <-F-Insufficient memory> ;003 SWAB R1 ;Make it blocks ;003 MOV R1,BUFSIZ ;Save the size ;003 MOV #OCHAN,R2 ;R2 = output channel number ;003 MOV R2,-(SP) ;Save it for later ;003 MOV BADLHD,-(SP) ;Save -> .BAD list ;003 MOV R2,$ODRCH ;Set up auxilliary output channel ;003 MOV R2,$DIRCH ;Set up the output directory channel ;003 MOV FSTSEG,$NXTSG ;Start at segment 1 or first private seg;003 CLR $NXTFL ;Clear to force in new segment ;003 MOV #ICHAN,$IDRCH ;Set up input directory channel ;003 MOV FSTSEG,$INXSG ;Start at segment 1 or first private seg;003 CLR $INXFL ;Clear to force in new segment ;003 BIT #FLG.DV,$OSFLG ;2 device? ;003 BNE SQUEZ2 ;Branch if so. ;003 SURE #INFILE,#MSGSQU,FG ;Ask if he's sure ;Check for foregrou;003 BNE 11$ ;Branch if we shouldn't squeeze the char;003 BR SQUEZ1 ;Squeeze the device ;003 ;003 RBOOT: BIT #FLG.DV,$OSFLG ;1 device squeeze? ;003 BNE 12$ ;Branch if not ;003 TST SQUSYS ;Were we squeezing the system device? ;003 BEQ 12$ ;Branch if not ;003 BIT #FL.WAT,$MFLAG ;/WAIT? ;003 BNE 12$ ;Branch if so. No re-boot ;003 MOV #DUP,R3 ;Point to filename SY:DUP.SAV ;003 MOV #17,R4 ;Overlay channel!!! ;003 CALL LOOKUP ;Look us up! ;003 BCC 10$ ;Branch if no error ;003 10$: BIT #FL.NBT,$MFLAG ;/X? ;003 BNE 12$ ;Branch if so. Don't re-boot ;003 MOV RELCOR,R5 ;R5 -> buffer space for squeeze ;003 JMP REBOOT ;Go boot SY: ;003 ;003 11$: CMP (SP)+,(SP)+ ;Clean stack from "Are you sure? N" ;003 CLR $AFLAG ;Forget we were going to do a squeeze ;so that the root does not chain to LD 12$: RETURN ;003 .DSABL LSB ;**-100 .SBTTL SQUEZ1 - Single device squeeze ;003 ;003 ;+ ;003 ; SQUEZ1 ;003 ; This is the single device squeeze code. ;003 ; ;003 ; (SP) -> .BAD list buffer ;003 ; 2(SP) = output channel number ;003 ; $DIRBF -> output directory buffer ;003 ; $DIRCH = output channel number ;003 ; $NXTSG = first segment to squeeze (1, or first prvt seg if VS s;003 ; $NXTFL = 0 ;003 ; $DIRB2 -> input directory buffer ;003 ; $IDRCH = input channel number ;003 ; $INXSG = first segment to squeeze ;003 ; $INXFL = 0 ;003 ; ;003 ; JMP SQUEZ1 ;003 ;- ;003 ;003 SQUEZ1:: ;003 MOV #OUTER1,OUTER ;Set up output error messager routine po;003 WAIT #WAITIN,#INFILE ;Wait for the input device to be mounted;003 ; ;003 ; Make sure we have a valid directory with no bad blocks in it ;003 ; ;003 ;+ ;ERROR 1$: CALL FNDEOS ;Look for the end of segment ;003 BCS 2$ ;Branch on error. We won't squeeze it ;003 ; <-F-Directory input error dev:> ;003 ; <-F-Invalid directory dev:> ;003 ;- MOV R0,R1 ;Save the found flag ;003 CALL WRTDIR ;Write the segment out ;003 BCC 3$ ;Branch if no error. ;003 ;+ ;ERROR MOV #DOE,R0 ;Set up the error code ;003 ; <-F-Directory output error dev:> ;003 2$: MOV R0,R1 ;Copy error code ;003 .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=NO,FILE=#INFILE ;003 ;- ;003 3$: TST R1 ;Was an entry found (more to come)? ;003 BNE 1$ ;Branch if so. See if it's there ;003 CALL RELINK ;Relink the directory ;003 ; ;003 ; Do the .BAD file search ;003 ; ;003 MOV (SP)+,R1 ;Restore the .BAD list buffer pointer ;003 CLR @R1 ;Flag no entries ;003 MOV #1,$NXTSG ;Start at the beginning of the directory;003 CLR $NXTFL ;First file ;003 4$: MOV #ASTBAD,R0 ;R0 -> *.BAD ;003 CALL FNDPRM ;Find any .BAD files ;003 ;+ ;ERROR BCS SQUER1 ;Branch on error ;003 ; <-F-Directory input error dev:> ;003 ; <-F-Invalid directory dev:> ;003 ;- TST R0 ;Any found? ;003 BEQ 5$ ;Branch if not. Go to common code (almo;003 MOV $STBLK,(R1)+ ;Save the start block for the file ;003 MOV DE.LEN(R0),(R1)+ ;and the length ;003 CLR @R1 ;Clear the next entry ;003 BR 4$ ;Try for another ;003 ;003 5$: CALL SCCA ;Inhibit ^C's ;003 BR SQUCOM ;Merge with common code ;003 ;**-95 .SBTTL SQUEZ2 - Two device squeeze ;003 ;003 ;+ ;**-2 ; SQUEZ2 ;003 ; This code handles the two device squeeze. It is called from SQUEEZE ;003 ; ;**-2 ; (SP) -> .BAD list buffer ;003 ; 2(SP) = output channel number ;003 ; $DIRBF -> output directory buffer ;003 ; $DIRCH = output channel number ;003 ; $NXTSG = 1 ;003 ; $NXTFL = 0 ;003 ; $DIRB2 -> input directory buffer ;003 ; $IDRCH = input channel number ;003 ; $INXSG = 1 ;003 ; $INXFL = 0 ;003 ; ;**-3 ; JMP SQUEZ2 ;003 ;- ;**-9 SQUEZ2:: ;003 MOV #OUTER2,OUTER ;Set up output error messager routine po;003 WAIT #WAITOU,#OUTFIL ;Wait for the output device to be mounte;003 MOV (SP)+,R1 ;Restore the .BAD list buffer pointer ;003 CLR @R1 ;Flag no entries ;003 1$: MOV #AST,R0 ;R0 -> *.* ;003 CALL FNDPRM ;Find any permanent file ;003 BCS SQUER1 ;Branch on error ;003 TST R0 ;Any found? ;003 BEQ 3$ ;Branch if not ;**-13 CMP #<^RBAD>,DE.TYP(R0) ;Is it a .BAD entry? ;003 BEQ 2$ ;Branch if so ;003 ;+ ;ERROR .ERR #OEAREA,#UIV,LEVEL=FATAL,RETURN=NO,FILE=#OUTFIL ;003 ; <-F-Uninitialized volume dev:> ;003 ;- ;003 2$: MOV $STBLK,(R1)+ ;Save the start block for the file ;003 MOV DE.LEN(R0),(R1)+ ;and the length ;003 CLR @R1 ;Clear the next entry ;003 BR 1$ ;Try for another ;003 ;003 3$: WAIT #WAITIN,#INFILE ;Wait for the input device to be mounted;003 .BR SQUCOM ;Go do common code ;003 ;**-75 .SBTTL SQUCOM - 1 and 2 device SQUEEZE common code ;003 ;003 .ENABL LSB ;003 SQUCOM:: ;003 CLR NOABRT ;Use as flag for .BAD clean-up at end ;003 MOV FSTSEG,$NXTSG ;Set up first output directory segment p;003 CLR $NXTFL ;Force in 1st output segment ;003 ;+ ;ERROR CALL NEXTFL ;Get first entry ;003 BCC 2$ ;Branch if no error ;003 SQUER1: MOV #OUTFIL,R3 ;R3 -> device name ;003 1$: MOV R0,R1 ;Copy the error code ;003 .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=NO,FILE=R3 ;003 ;- ;003 2$: MOV R0,R4 ;R4 -> entry ;003 MOV #OUTST,R0 ;R0 -> .DSTATUS info ;003 MOV #$OSFLG,R1 ;R1 -> output device flag ;003 MOV (SP)+,R2 ;R2 = channel number ;003 CALL GTDVSZ ;Get the device size ;003 MOV $DIRBF,R0 ;R0 -> directory header ;003 MOV (R0)+,R3 ;R3 = number of available segments and s;003 CLR (R0)+ ;Clear next segment ;003 CLR $NXTSG ;Both places ;003 MOV FSTSEG,@R0 ;Highest open is 1, or first private seg;003 MOV (R0)+,$HISEG ;Both places ;003 CMP (R0)+,(R0)+ ;Skip extra bytes and start block ;003 MOV #EMPTYF,R2 ;R2 -> empty entry ;003 MOV (R2)+,(R0)+ ;Copy the file status ;003 MOV (R2)+,(R0)+ ; and the 1st word of the filename ;003 MOV (R2)+,(R0)+ ; and the 2nd word of the filename ;003 MOV (R2)+,(R0)+ ; and the filetype ;003 ASL R3 ;Number of directory blocks = available ;003 ADD #6,R3 ;Skip boot and home blocks ;003 SUB R3,R1 ;All of that out of the device size ;003 TST SQUVS0 ;Are we squeezing VS0 as system device ;003 BEQ 101$ ; No - use computed size ;003 SUB SHRSIZ,R1 ; Yes - take out shared files' size too;003 101$: MOV R1,(R0)+ ;Move in device size as filesize ;003 TST (R2)+ ;Skip fake filesize ;003 MOV (R2)+,(R0)+ ;Move in job/channel ;003 MOV (R2)+,(R0)+ ;Move in date ;003 ADD $EXTBY,R0 ;R0 -> next entry ;003 MOV #DS.EOS,@R0 ;Make it end of segment ;003 ;+ ;ERROR FIND: CALL INXTFL ;Get -> 1st input file ;003 BCC 3$ ;Branch if no error ;003 MOV #INFILE,R3 ;R3 -> input device ;003 BR 1$ ;Go give error ;003 ;- ;003 3$: MOV R0,R5 ;Is there an entry? ;003 BEQ 11$ ;No. Done. ;003 BIT #,@R5 ;Is it one to ignore? ;003 BNE FIND ;Branch if so. Get next entry ;003 CMP #<^RBAD>,DE.TYP(R5) ;Is it a .BAD file? ;003 BEQ FIND ;Branch if so. Don't copy it. ;003 RECREA: MOV R5,PSEG ;Preserve -> current entry ;003 ;+ ;ERROR CALL CREAT1 ;Create the entry ;003 BCC 5$ ;Branch if no error ;003 SQUER2: CMP R0,#FE.DVF ;Is it a device full error? ;003 BEQ 4$ ;Branch if so ;**-35 CMP R0,#FE.DFL ;Is it a directory full? ;003 BNE SQUER1 ;Branch if not ;003 4$: MOV R0,R1 ;Set error code ;003 .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=YES,FILE=#OUTFIL ;003 ;- TST $DIRTY ;Was the last segment writen to? ;003 BNE 13$ ;Branch if so. Go write out last segmen;003 JMP ABORT ;003 ;003 5$: MOV R4,-(SP) ;Save R4 ;003 MOV PSEG,R2 ;R2 -> current input entry ;003 MOV REDSTR,R5 ;R5 = input start block number ;003 MOV WRTSTR,R4 ;R4 = output start block number ;003 BIT #FLG.DV,$OSFLG ;Single device squeeze? ;003 BNE 6$ ;Branch if not ;003 CMP R4,R5 ;Read start and write start the same? ;003 BEQ 10$ ;Branch if so. No movement needed. ;003 6$: MOV BUFSIZ,R3 ;R3 = buffer size in blocks ;003 REREAD: MOV REDEND,R1 ;R1 = number of blocks to copy ;003 BEQ 10$ ;Branch if done ;003 CMP R1,R3 ;Enough room in buffer? ;003 BLOS 7$ ;Branch if not ;003 MOV R3,R1 ;Use buffer size ;003 7$: SWAB R1 ;R1 = number of words ;003 8$: READ #IOAREA,#ICHAN,IBFBEG,R1,R5 ;Read it ;003 BCS INER12 ;Go process the error ;003 SKIP: ADD #377,R0 ;Round up to block boundary ;003 BIC #377,R0 ;Get rid of low bits ;003 MOV R0,R1 ;Get actual number of words read ;003 WRITE #IOAREA,#OCHAN,IBFBEG,R1,R4 ;Write it ;003 BCC 9$ ;Branch if no error ;003 JMP @OUTER ;Go to error routine ;003 ;003 9$: MOV R1,R0 ;R0 = word count ;003 CLRB R0 ;Clear low byte ;003 SWAB R0 ;Make it blocks ;003 ADD R0,R5 ;Bump input block number ;003 ADD R0,R4 ;Bump output block number ;003 SUB R0,REDEND ;Subtract from # of blocks left ;003 BNE REREAD ;Go do it again, if anything left to do.;003 10$: MOV (SP)+,R4 ;Restore R4 ;003 BR FIND ;Go find another entry ;003 ;003 11$: MOV #1,NOABRT ;Flag that we're starting .BAD clean-up ;003 12$: MOV BADLHD,R1 ;Get pointer to .BAD list ;003 TST @R1 ;Are there any? ;003 BEQ 13$ ;Branch if not ;003 CALL CREAT2 ;Go create it ;003 BCC 12$ ;Go do the next one ;003 102$: BR SQUER2 ;Branch on error ;003 ;003 13$: CALL WRTDIR ;Write the last output segment ;003 BIT #FLG.DV,$OSFLG ;2 device squeeze? ;003 BNE 15$ ;Branch if so ;003 TST $NXTSG ;Is there a next segment? ;003 BEQ 14$ ;Branch if not ;003 CALL SWAPBF ;Get it ;003 CALL WRTDIR ;Write it out ;003 14$: TST SQUVS0 ;Squeezing VS0 as system device? ;003 BEQ 15$ ; No - that's it ;003 TST SEG1FG ; Yes - segment 1 updated? ;003 BNE 15$ ; Yes - that's it ;003 MOV #1,$NXTSG ; No - setup to read segment 1 ;003 CLR $NXTFL ;Force it in ;003 MOV $HISEG,R4 ;Save real highest segment ;003 CALL NEXTFL ;Read it ;003 BCS 102$ ;Error on read ;003 MOV $DIRBF,R3 ;Get buffer addr ;003 MOV R4,DH.HI(R3) ;Set highest segment open ;003 CALL WRTDIR ;Write back to segment 1 ;003 15$: JMP RBOOT ;Go clean up ;003 .DSABL LSB ;003 ;**-5 .ENABL LSB ;003 INER12:: ;003 CMP R1,#400 ;Are we doing single block transfers? ;003 BNE 2$ ;Branch if not ;003 MOV @R2,-(SP) ;Save the status word ;003 MOV INFILE,@R2 ;Set up device name ;003 ;+ ;ERROR .ERR #ERAREA,#FE.INE,LEVEL=FATAL,RETURN=YES,FILE=R2 ;003 ;- MOV (SP)+,@R2 ;Restore the status word ;003 BIT #FLG.DV,$OSFLG ;2 device squeeze? ;003 BEQ 1$ ;Branch if not ;003 MOV #1,R0 ;Fake that something was read ;003 BR SKIP ;Finish copying file ;003 ;003 1$: CMP R4,REDSTR ;Have we written over the file? ;003 BLOS 8$ ;Branch if not. ;003 BR 5$ ;Else fix it ;003 ;003 OUTER1:: ;003 MOV R1,R0 ;R0 = # words read ;003 SWAB R0 ;Get # blocks read ;003 ADD R4,R0 ;Get highest block written ;003 CMP R0,REDSTR ;Is it above start of file we're copying;003 BHI 4$ ;Branch if so ;003 OUTER2:: ;003 CMP R1,#400 ;Single block transfer mode? ;003 BEQ 3$ ;Yes. Do recovery ;003 2$: MOV #1,R3 ;Go to single block mode ;003 JMP REREAD ;Start again on the read ;003 ;003 ;+ ;ERROR 3$: .ERR #ERAREA,#FE.OPE,LEVEL=WARN,RETURN=YES,FILE=#OUTFIL ;003 ; <-F-Output error dev:> ;003 ;- MOV R2,R5 ;R5 -> current input file entry ;003 MOV R4,R1 ;R1 = current output block ;003 CALL SETUP ;Set up some things ;003 MOV BADLHD,R0 ;R0 -> bad block list ;003 CMP -(R0),-(R0) ;R0 -> previous entry ;003 MOV R0,BADLHD ;Save it ;003 MOV R1,(R0)+ ;Store block number ;003 MOV #1,@R0 ; and the size ;003 TST (SP)+ ;Clean the stack ;003 JMP RECREA ;Restart operation ;003 ;003 4$: CMP R0,R5 ;Last block "written" >= 1st block read?;003 BLOS 5$ ;Branch if not ;003 WRITE #IOAREA,#OCHAN,IBFBEG,R1,R5 ;Else write it back out ;003 5$: MOV DE.LEN(R2),R1 ;R1 = # blocks in file ;003 SUB REDEND,R1 ;R1 = # blocks transferred/left to trans;003 MOV R1,REDEND ;Save it ;003 6$: MOV REDEND,R1 ;R1 = # blocks left to read ;003 BEQ 8$ ;Branch if done ;003 CMP R1,R3 ;Enough room in buffer? ;003 BLOS 7$ ;Branch if not ;003 MOV R3,R1 ;Use buffer size ;003 7$: SUB R1,R4 ;Back up input pointer ;003 SUB R1,R5 ; and the output pointer ;003 SWAB R1 ;R1 = number of words ;003 READ #IOAREA,#ICHAN,IBFBEG,R1,R4 ;Read it ;003 WRITE #IOAREA,#OCHAN,IBFBEG,R1,R5 ;Write it ;003 MOV R1,R0 ;R0 = word count ;003 CLRB R0 ;Clear low byte ;003 SWAB R0 ;Make it blocks ;003 SUB R0,REDEND ;Subtract from # of blocks left ;003 BNE 6$ ;Go do it again, if anything left to do.;003 8$: CALL SETUP ;Set up some things ;003 MOV REDSTR,R0 ;R0 = start block for reads ;003 SUB WRTSTR,R0 ;R0 = length of empty before file ;003 MOV R2,-(SP) ;Save -> current file ;003 MOV #EMPTYF,R5 ;R5 -> fake empty entry ;003 MOV R0,DE.LEN(R5) ;Fix size ;003 TST $NXTSG ;Was this segment split? ;003 BEQ 9$ ;Branch if not ;003 CLR $NXTSG ;Say that it wasn't ;003 DEC $HISEG ;Fix hi segment in use ;003 9$: CALL CREAT1 ;Create the empty ;003 BCC 11$ ;Branch if no error ;003 10$: CMP (SP)+,(SP)+ ;Clean stack ;003 JMP SQUER2 ;Do the error ;003 ;003 11$: MOV @SP,R5 ;R5 -> current entry ;003 CALL CREAT1 ;"Create" the file ;003 BCS 10$ ;Branch on error ;003 CMP (SP)+,(SP)+ ;Clean stack ;003 JMP FIND ;Do next file ;003 ;003 SETUP: MOV SAVENT,R4 ;R4 -> current output file entry (offset;003 ADD $DIRBF,R4 ;Make it absolute ;003 MOV #DS.EMP,@R4 ;Make it empty ;003 MOV SAVESZ,DE.LEN(R4) ;Put in old empty size ;003 MOV R4,R0 ;R0 -> current entry ;003 ADD #DE.SIZ,R0 ;R0 -> next entry ;003 ADD $EXTBY,R0 ;Add in extra bytes ;003 MOV #DS.EOS,@R0 ;Make it end-of-segment ;003 MOV WRTSTR,$STBLK ;Fix the starting block number ;003 RETURN ;003 .DSABL LSB ;003 ;003 .SBTTL CREAT1 - Create an entry in a directory ;003 ;003 ;+ ;**-2 ; CREAT1 ;003 ; This routine creates a new entry in a directory. ;003 ; ;**-5 ; R4 -> current position in output segment ;003 ; R5 -> current position in input segment ;003 ; $STBLK = start block number for entry -> by R4 ;003 ; ;**-3 ; CALL CREAT1 ;003 ; ;003 ; C-bit = 0 => success ;003 ; R4 -> next entry in output directory ;003 ; R0 - R5 modified ;003 ; ;003 ; C-bit = 1 => error ;003 ; R0 = error code ;003 ; R1 - R5 modified ;003 ;- ;**-1 .ENABL LSB ;003 CREAT1:: ;003 BIT #DS.EMP,@R4 ;Is this an empty entry? ;003 BNE 5$ ;Branch if so ;003 BIT #FLG.DV,$OSFLG ;1 or 2 device squeeze ;**-44 BNE 4$ ;Branch if 2 device ;003 CALL WRTDIR ;Write out this segment ;003 BCC 1$ ;Branch if no error ;003 ;+ ;ERROR MOV #DOE,R0 ;Set error code ;003 ; <-F-Directory output error> ;003 BR 13$ ;Return error ;003 ;- ;003 1$: TST $NXTSG ;Any next segment? ;003 BEQ 3$ ;Branch if not ;003 CALL SWAPBF ;Swap the output data segments ;003 MOV $NXTFL,R0 ;Get -> first entry ;003 2$: MOV R0,R4 ;Did it find and entry? ;003 BNE 5$ ;Branch if so ;003 ;+ ;ERROR 3$: MOV #FE.DFL,R0 ;Set the error code ;003 ; <-F-Directory full> ;003 BR 13$ ;Give the error ;003 ;- ;003 4$: CLR $NXTFL ;Clear to force next segment in ;003 CALL NEXTFL ;Red in next segment if it exists ;003 BCS 13$ ;Error! ;003 BR 2$ ;Continue ;003 ;003 5$: CMP DE.LEN(R5),DE.LEN(R4) ;Is the entry big enough ;003 BLOS 6$ ;Branch if so ;003 ;+ ;ERROR MOV #FE.DVF,R0 ;Set the error code ;003 ; <-F-Device full> ;003 BR 13$ ;Give the error ;003 ;- ;003 6$: MOV R4,SAVENT ;Save the -> entry ;003 SUB $DIRBF,SAVENT ;Make it relative to beginning of buffer;003 MOV DE.LEN(R4),SAVESZ ;Save size of entry ;003 MOV $STBLK,R0 ;R0 = start block for file ;003 ADD DE.LEN(R5),R0 ;R0 = start block for next file ;003 MOV BADLHD,R1 ;Get pointer to bad block list ;003 TST @R1 ;Is there an entry there? ;003 BEQ 9$ ;Branch if none ;003 CMP R0,@R1 ;Does the file fit before the bad block?;003 BLOS 9$ ;Branch if so ;003 CREAT2: MOV R5,-(SP) ;Save R5 ;003 MOV #EMPTYF,R5 ;R5 -> dummy empty entry to create ;003 MOV (R1)+,R0 ;R0 = start block of bad block ;003 SUB $STBLK,R0 ;R0 = size of empty ;003 MOV R1,-(SP) ;Save R1 ;003 MOV R0,DE.LEN(R5) ;Set up the length ;003 BEQ 65$ ;Skip if zero length file ;003 CALL CREAT1 ;Go create the empty! ;003 65$: MOV (SP)+,R1 ;Restore R1 ;003 BCS 8$ ;Branch on error ;003 MOV #FILBAD,R5 ;R5 -> FILE.BAD entry ;003 MOV (R1)+,DE.LEN(R5) ;Save the .BAD length ;003 7$: MOV R1,BADLHD ;Save new pointer into .BAD list ;003 CALL CREAT1 ;Create the .BAD file ;003 8$: MOV (SP)+,R5 ;Restore input entry pointer ;003 BCS 13$ ;Branch on error ;003 TST NOABRT ;Are we cleaning up .BAD after squeeze? ;003 BNE 12$ ;Branch if so ;003 BR CREAT1 ;Go create it ;003 ;003 9$: CMP DE.LEN(R5),DE.LEN(R4) ;Does the input file fit exactly? ;003 BEQ 10$ ;Branch if so. No need to shuffle direc;003 CALL SHFFL1 ;Shuffle directory down an entry. ;003 BCS 13$ ;Branch on error. Code returned in R0 ;003 10$: INC $DIRTY ;Flag directory re-write needed ;003 MOV $STBLK,WRTSTR ;Save the write start block ;003 MOV $ISTBL,REDSTR ;Save the read start block ;003 MOV DE.LEN(R5),REDEND ;Save the number of blocks ;003 MOV (R5)+,(R4)+ ;Copy the file status ;003 MOV (R5)+,(R4)+ ; and the 1st word of the filename ;003 MOV (R5)+,(R4)+ ; and the 2nd word of the filename ;003 MOV (R5)+,(R4)+ ; and the filetype ;003 MOV @R4,R3 ;Save the size of the empty entry ;003 SUB @R5,R3 ;R3 = size of following empty ;003 MOV (R5)+,(R4)+ ;Copy the size of the file ;003 MOV (R5)+,(R4)+ ; and the data length ;003 MOV (R5)+,(R4)+ ; and the date ;003 ADD $EXTBY,R4 ;R4 -> next entry ;003 TST R3 ;Was there anything left for next empty?;003 BEQ 11$ ;Branch if not. No next empty ;003 MOV R3,DE.LEN(R4) ;Save the new length ;003 11$: ADD REDEND,$STBLK ;Update the start block for entry -> by ;003 12$: TST (PC)+ ;Clear C-bit ;003 13$: SEC ;Set C-bit ;003 RETURN ;**-45 .DSABL LSB ;003 .SBTTL SHFFL1 - Shuffle the directory down ;003 ;003 ;+ ;**-2 ; SHFFL1 ;003 ; This routine shuffles the directory down to make space for an entry ;003 ; ;**-2 ; R4 -> Current entry in output directory ;003 ; R5 -> Current entry in input directory ;003 ; $DIRBF -> Directory buffer ;003 ; $EXTBY = Number of extra bytes per entry ;003 ; ;003 ; JSR PC,SHFFL1 ;003 ; ;003 ; R0 - R2 modified ;003 ;- ;**-3 SHFFL1:: ;003 SAVE35 ;Save R3-R5 ;003 MOV #DE.SIZ,R3 ;R3 = size of a directory entry ;003 ADD $EXTBY,R3 ; plus extra bytes ;003 MOV R4,R2 ;R5 -> current position ;003 MOV R4,R0 ;R0 -> current position ;003 1$: BIT #DS.EOS,@R0 ;At the end of segment yet? ;003 BNE 2$ ;Branch if so ;003 ADD R3,R0 ;Point to next entry ;003 BR 1$ ;Try again ;003 ;003 2$: MOV R0,R1 ;R1 -> end of segment entry ;003 ADD R3,R1 ;R1 -> past end of segment ;003 MOV R1,R4 ;R4 -> past end of segment ;003 SUB $DIRBF,R1 ;Make R1 a relative offset ;003 CMP #,R1 ;Are we past the end of the segment? ;003 BLOS EXTDR1 ;Branch if so. Extend the directory ;003 MOV @R0,@R4 ;Copy a word down ;003 3$: CMP R0,R2 ;Done? ;003 BEQ 4$ ;Branch if so ;003 MOV -(R0),-(R4) ;Copy the segment down ;003 BR 3$ ;See if we're done ;003 ;003 4$: CLC ;Everything is ok ;003 5$: RETURN ;003 ;**-40 .SBTTL EXTDR1 - Extend a directory segment ;003 ;003 ;+ ;**-3 ; EXTDR1 ;003 ; This routine is a modification of the one in the CREATE code. It spli;003 ; a directory segment at the end-of-segment, making an empty in the new ;003 ; segment the size of the previous empty minus the size of the current i;003 ; file. The entry before the EOS must be an empty! ;003 ; ;**-3 ; R0 -> EOS entry for this segment ;003 ; R2 -> current entry ;003 ; R5 -> current entry in input directory ;003 ; ;**-3 ; All registers modified ;003 ;- ;**-8 EXTDR1:: ;003 MOV SP,XDR1SP ;Save SP to make error cleanup easy MOV R2,-(SP) ;Save pointer to current entry ;003 MOV $DIRBF,R4 ;R4 -> beginning of the directory buffer;003 SUB R4,@SP ;Make it absolute ;003 CMP $HISEG,@R4 ;Any segments left to open? ;003 BLT 1$ ;Branch if so ;003 ;+ ;ERROR MOV #FE.DFL,R0 ;Flag the error ;003 BR 9$ ;Return ;003 ; <-F-Directory full dev:> ;003 ;- ;003 1$: MOV R0,-(SP) ;Save R0 ;003 CALL SCCA ;Inhibit ^C ;003 MOV (SP)+,R0 ;Restore R0 ;003 MOV R4,R3 ;R3 -> output directory buffer ;003 MOV DE.LEN(R5),R0 ;R0 = size of empty we want ;003 MOV DE.LEN(R2),-(SP) ;TOS = size of empty in output director;003 MOV R0,DE.LEN(R2) ;Fix it to be what we want ;003 SUB R0,@SP ;TOS = size of empty we'll create in nex;003 MOV R2,R1 ;R1 -> current entry in output segment ;003 MOV $STBLK,R5 ;R5 = start blk of empty in output direc;003 ADD R0,R5 ;R5 = start blk of next segment ;003 MOV @R1,-(SP) ;Save status of entry for later ;003 MOV $HISEG,R2 ;R2 = highest segment open ;003 INC R2 ;Bump the highest segment open ;003 MOV DH.NXT(R3),-(SP) ;Save the link to the next segment ;003 MOV R2,DH.NXT(R3) ;Set up new link ;003 CALL WRTDIR ;Re-write this segment (shortened) ;003 BCS 6$ ;Error!!!! ;003 MOV R3,R0 ;R0 -> output directory buffer ;003 MOV R3,R4 ;R4 -> output directory buffer ;003 ADD #,R4 ;R4 -> end of directory buffer ;003 TST (R0)+ ;Leave # available segments alone ;003 MOV (SP)+,(R0)+ ;Copy link to next segment ;003 MOV (SP)+,@R1 ;Restore file status ;003 MOV (SP)+,DE.LEN(R1) ;Set up the size of the entry ;003 2$: CMP (R0)+,(R0)+ ;Skip highest segment, # extra bytes ;003 MOV R5,(R0)+ ;Save start block for file in this segme;003 3$: MOV (R1)+,(R0)+ ;Slide the directory up ;003 CMP R1,R4 ;Done? ;003 BLOS 3$ ;Branch if not ;003 MOV R2,R5 ;R5 = segment number of this segment ;003 ASL R5 ;Make it a block number ;003 ADD #4,R5 ;Starts at block # 6 ;003 MOV R5,$DIRSG ;WRTDIR needs to know the block number ;003 BIT #FLG.DV,$OSFLG ;1 or 2 device squeeze ;003 BNE 4$ ;Branch if 2 ;003 MOV R3,R0 ;R0 -> directory buffer ;003 SUB $DIRBF,R3 ;Make R3 relative ;003 ADD #DH.STB,R0 ;R0 -> start block for files in segment ;003 MOV (R0)+,$STBLK ;Set up start block ;003 MOV R0,$NXTFL ;Set up -> next file ;003 CLR $LSTLN ;Last length = 0 ;003 CLR $NXTSG ;Next segment = 0 ;003 MOV R2,$HISEG ;Set up hi segment ;003 MOV SP,$DIRTY ;Flag it as written in ;003 CALL SWAPBF ;Swap data segments with other output se;003 ADD $DIRBF,R3 ;Make R3 absolute ;003 BR 5$ ; ;**-13 4$: CALL WRTDIR ;Write the segment out ;003 BCS 6$ ;Error!!!! ;003 5$: MOV R2,-(SP) ;Put new segment number on stack ;003 DEC @SP ;Make it the old segment number ;003 MOV #1,$NXTSG ;Read in segment #1 ;003 CLR $NXTFL ;Force it in ;003 CALL NEXTFL ;Get it in ;003 ;+ ;ERROR BCS 9$ ;Error!!!! ;003 ; <-F-Invalid directory dev:> ;003 ; <-F-Directory input error dev:> ;003 ;- MOV R2,DH.HI(R3) ;Set up the new high segment ;003 MOV R2,$HISEG ;Remember it ;003 CALL WRTDIR ;Write segment #1 back ;003 BCC 7$ ;Branch if no error ;003 ;+ ;ERROR 6$: MOV #DOE,R0 ;Set directory output error ;003 BR 9$ ; ;003 ; <-F-Directory output error dev:> ;003 ;- ;003 7$: INC SEG1FG ;Indicate segment 1 updated ;003 CALL NOSCCA ;Allow ^C's ;003 MOV (SP)+,$NXTSG ;Restore the segment number ;003 CLR $NXTFL ;No next file to force it in ;003 MOV @SP,R4 ;R4 -> current entry in output directory;003 ADD $DIRBF,R4 ;Point it into buffer ;003 8$: CALL NEXTFL ;Get a file ;003 BCS 9$ ;Branch on error ;003 CMP R0,R4 ;Is this it? ;003 BNE 8$ ;Branch if not ;003 MOV R4,6(SP) ;!!Return the correct pointer ;003 TST (PC)+ ;Clear carry ;003 9$: SEC ;Indicate error ;003 MOV XDR1SP,SP ;*C*Clean stack (the easy way!) RETURN ;**-20 ;003 .SBTTL RELINK - Relink the directory ;003 ;003 ;+ ;**-3 ; This routine relinks the directory so that the logical and physical ;003 ; segments are the same. If squeezing VS0 as system device, shared ;003 ; directory better be in right order to begin with ;003 ; ;**-4 ; $DIRBF -> primary directory buffer ;003 ; $DIRB2 -> secondary directory buffer ;003 ; input device opened NFS on ICHAN ;003 ;- ;**-1 RELINK:: ;003 CALL SCCA ;Can't stop now! ;003 MOV #-1,NOABRT ;Can't abort either!!! ;003 MOV $DIRBF,R5 ;R5 -> primary directory buffer ;003 MOV $DIRB2,R4 ;R4 -> secondary directory buffer ;003 MOV #1,R3 ;R3 = current segment number ;003 1$: READSG SEG=R3,BUF=R5 ;Read in the segment ;003 2$: MOV DH.NXT(R5),R1 ;R1 = next (physical) segment # ;003 BEQ 5$ ;Branch if done ;003 TSTB PSEG(R1) ;Is it really someplace else? ;003 BEQ 4$ ;Branch if not ;003 3$: MOVB PSEG(R1),-(SP) ;Save the location where it's at ;003 CLRB PSEG(R1) ;It won't be there for long ;003 MOV (SP)+,R1 ;Get the segment number back ;003 BIC #^C<37>,R1 ;Leave only segment number ;003 TSTB PSEG(R1) ;Is this REALLY where it is? ;003 BNE 3$ ;Branch if not ;003 MOV R1,DH.NXT(R5) ;Stuff the real link word ;003 WRITSG SEG=R3,BUF=R5 ;Write out the updated segment ;003 4$: INC R3 ;R3 = next (logical) segment # ;003 CMP R3,R1 ;Are the logical and physical the same? ;003 BEQ 1$ ;Branch if so. Go read it in ;003 ; At this point, we swap the 2 segments on disk ;003 MOVB R1,PSEG(R3) ;Save where we're moving the segment to ;003 MOV R3,DH.NXT(R5) ;Set the new next segment ;003 MOV R3,R2 ;R2 = next segment ;003 DEC R2 ;R2 = current segment ;003 WRITSG BUF=R5 ;Write the segment back out ;003 READSG SEG=R1,BUF=R5 ;Read in the next segment ;003 READSG SEG=R3,BUF=R4 ;Read in the the one we've got to move ;003 WRITSG BUF=R5 ;Write it back out ;003 WRITSG SEG=R1,BUF=R4 ;Write out the other one ;003 BR 2$ ;Continue ;003 ;003 5$: TST NOABRT ;Did we get any errors? ;003 BMI 6$ ;Branch if not ;003 JMP ABORT ;Else get out now ;003 ;003 6$: CALL NOSCCA ;Allow ^C ;003 RETURN ;**-23 ;003 .SBTTL RDSEG - Read a directory segment ;003 .SBTTL WTSEG - Write a directory segment ;003 ;003 ;+ ;**-3 ; RDSEG ;003 ; WTSEG ;003 ; These two routines read and write directory segments. ;003 ; ;003 ; DIOBUF -> buffer ;003 ; NOABRT = 0 => abort immediately on error ;003 ; NOABRT <> 0 => return to caller on error ;003 ; ;003 ; CALL RDSEG ;003 ; CALL WTSEG ;003 ; ;003 ; C-bit = 0 => success ;003 ; R0 = random ;003 ; C-bit = 1 => error ;003 ; R0 = error code ;003 ; NOABRT = 1 ;003 ;- ;**-1 .ENABL LSB ;003 ;+ ;ERROR RDSEG: MOV #DIE,R0 ;Error code and read flag ;003 BR 1$ ;003 ;003 WTSEG: MOV #DOE,R0 ;Error code and write flag ;003 1$: SAVE02 ;Preserve R1 and R2 ;003 ;- MOV R0,R1 ;Copy error code, flag ;003 ASL R2 ;Segments are 2 blocks long ;003 ADD #4,R2 ;Correct for directory start block bias ;003 CMP R1,#DIE ;Input? ;003 BNE 2$ ;Branch if not ;003 ;+ ;ERROR READ #DIOARA,BLK=R2 ;Read it in ;003 BCS 3$ ;Branch on error ;003 BR 5$ ; ;003 ;003 2$: WRITE #DIOARA,BLK=R2 ;Write out the directory ;003 BCC 5$ ;003 3$: .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=YES,FILE=#INFILE ;003 ;- TST NOABRT ;Can we abort now? ;003 BNE 4$ ;Branch if not ;003 JMP ABORT ;Yes. Get out ;003 ;003 4$: MOV #1,NOABRT ;Flag that an error occurred. ;003 SEC ;Flag the error ;003 5$: RETURN ; ;003 .DSABL LSB ;003 ;003 .SBTTL INXTFL - Get Next File in Input Directory ;003 ;003 ;+ ;003 ; INXTFL ;003 ;- ;003 ;003 INXTFL: CALL SAVEPT ;Save and set up pertinent data ;003 CALL NEXTFL ;Get next file ;003 RETURN ;**-8 .SBTTL SAVEPT - Save and Set Up Directory Scan Data ;003 ;003 ;+ ;003 ; SAVEPT ;003 ; This co-routine saves the data used by the directory munging routines ;003 ; and sets up to use the output directory data. When re-entered, it res;003 ; the data for both input and output ;003 ; ;003 ; CALL SAVEPT ;003 ;- ;003 ;003 SAVEPT: MOV R1,-(SP) ;Save R1 ;003 MOV #$IAVAL,R1 ;R1 -> output directory data ;003 CALL SWAP ;Swap the data segments ;003 MOV (SP)+,R1 ;Restore R1 ;003 BIT #1,@SP ;TOS odd? !!!!Don't touch C-bit!!!! ;003 BNE 1$ ;Branch if so. We're returning to self ;003 JSR PC,@(SP)+ ;Return to caller ;003 INC @SP ;Set recursive flag ;003 BR SAVEPT ;Go restore data ;003 ;003 1$: DEC @SP ;Clear flag bit ;003 RETURN ;Return to caller ;003 ;003 .SBTTL SWAPBF ;003 ;003 ;+ ;003 ; SWAPBF ;003 ;- ;003 ;003 SWAPBF: MOV R1,-(SP) ;Preserve R1 ;003 MOV #$OAVAL,R1 ;R1 -> alternate input directory data ;003 CALL SWAP ;Swap the data segments ;003 MOV (SP)+,R1 ;Restore R1 ;003 RETURN ;003 ;003 .SBTTL SWAP ;003 ;003 ;+ ;003 ; SWAP ;003 ;- ;003 ;003 SWAP: SAVE02 ;Preserve volatile registers ;003 MOV #$AVAIL,R0 ;R0 -> input directory data ;003 MOV #DDATSZ,R2 ;R2 = # words to save ;003 1$: MOV @R0,-(SP) ;Save a word ;003 MOV @R1,(R0)+ ;Copy 1 ;003 MOV (SP)+,(R1)+ ;Copy the other ;003 DEC R2 ;Decrement the count ;003 BNE 1$ ;Loop til done ;003 RETURN ;003 ;003 .END