.TITLE KERDF - Default file processing routines .SBTTL N Bush ; Version 1.0.000 .IDENT /1.0.000/ ; Directives .LIBRARY /KERMLB/ ; Pro/Kermit macro library .LIBRARY /LB:[1,5]RMSMAC/ ; RMS-11 macro library .SBTTL Revision History ; ; 1.0.000 By: Nick Bush On: 19-December-1983 ; Create this module ; .SBTTL .MCALLs for RSX and RMS directives ; The following are the various MCALLs that KERXK uses. .MCALL FAB$B ; To build FAB for RMS .MCALL RAB$B ; To build RAB for RMS .MCALL $OPEN ; Open a file using RMS .MCALL $CLOSE ; Close a file using RMS .MCALL $CONNECT ; Connect RAB to FAB .MCALL $DISCONNECT ; Disconnect RAB and FAB .MCALL $GET ; Read a record .MCALL $PUT ; Write a record .MCALL $UPDATE ; Update record in place .MCALL $REWIND ; Rewind stream .MCALL $CREATE ; Create a file .MCALL $STORE ; Store an RMS field .MCALL $FETCH ; Fetch an RMS field .MCALL $COMPARE ; Compare value with RMS field .MCALL ORG$ ; Declare type of file access we need ORG$ SEQ, ; Type of access we need ; The following causes the KERMIT definitions to be read and defined .MCALL KERDEF ; Get the KERMIT definitions KERDEF ; Define all of the KERMIT symbols .MCALL BLOCK ; Macro to define blocks .MCALL MSG ; Text definition macro .SBTTL Local symbol definitions ; The following are some local symbol defintions used in the defaults file ;processing DF.MRS= 64. ; Maximum record size is 64. ; A record in the defaults file is of the form: ;*** Insert box here BLOCK DF ; Define DF.xxx symbols for record offsets .X RTP ; Record type code .XX RSZ ; Size of data portion of record .XX OFS ; Offset to data portion of record .X HLN,0 ; Length of header .SBTTL Impure storage ; The following are the local impure storage locations for KERDF. .PSECT $OWN$, D DF.FAB: FAB$B ; Define the FAB F$FAC FB$GET!FB$PUT!FB$UPD ; Want to be able to do a few operations F$FNA M$DFLN ; Address of name string F$FNS DFLN$L ; Length of name string F$LCH DFLLUN ; Logical unit number to use F$MRS DF.MRS ; Maximum record size F$ORG FB$SEQ ; Sequential file F$RFM FB$FIX ; Fixed record length FAB$E ; End of FAB DF.RAB: RAB$B ; Define the RAB R$FAB DF.FAB ; Address of FAB R$RAC RB$SEQ ; Sequential access R$RBF DF.BUF ; Record buffer address R$RSZ DF.MRS ; Recurd buffer size R$UBF DF.BUF ; User buffer address R$USZ DF.MRS ; Buffer size RAB$E ; End of RAB DF.BUF: .BLKB DF.MRS ; Record buffer DFLOPN: .BLKB 1 ; Flag whether file is open DFLRCR: .BLKB 1 ; Flag whether record is current .EVEN ; Back to word boundary ; Pure data .PSECT $PLIT$,RO,D ; Put in correct place MSG DFLN, ; File name .SBTTL DF.INI - Initialize the default file handling ;++ ; This routine will initialize the default file processing. It will ;determine if the default file exists, and if not, it will create it ;as an empty file. The file will be left in a state such that we can ;read and write to it. ; ; Usage: ; ; Macro: ; JSR PC,DF.INI ; (Return here always) ; ;-- .PSECT $CODE$, RO DF.INI::CLRB DFLRCR ; No current record at all ; First try to open the file MOV #DF.FAB,R0 ; Point at the FAB $OPEN R0 ; Open the file $COMPARE #SU$SUC,STS,R0 ; Did we successfully open the file? BEQ 10$ ; Yes, set up RAB ; Here if we could not open the file for some reason. Try to create a new ;one $CREATE R0 ; Attempt to create the file $COMPARE #SU$SUC,STS,R0 ; Could we? BNE 15$ ; No, give up ; Here after file has either been OPENed or CREATEd. Connect up the RAB 10$: MOV #DF.RAB,R0 ; Point at the RAB $CONNECT R0 ; Connect it up $COMPARE #SU$SUC,STS,R0 ; Did it work? BEQ 20$ ; Yes, remember that MOV #DF.FAB,R0 ; No, point back at FAB $CLOSE R0 ; Close the file 15$: CLRB DFLOPN ; And remember file is not open RTS PC ; Give up ; Here when file is open and RAB connected. Remember the file is ok and return 20$: MOVB #1,DFLOPN ; Flag file is open RTS PC ; And return .SBTTL DF.FIN - Finish out default file processing ;++ ; This routine will terminate the default file processing. It will ;close the defaults file. ; ; Usage: ; ; Macro: ; JSR PC,DF.FIN ; (return here always) ; ;-- DF.FIN::TSTB DFLOPN ; File open? BEQ 99$ ; No, nothing to close MOV #DF.RAB,R0 ; Point at RAB $DISCONNECT R0 ; Disconnect it MOV #DF.FAB,R0 ; Point at FAB $CLOSE R0 ; Close the file 99$: RTS PC ; And return .SBTTL DF.RD - Read a record from the default file ;++ ; This routine will read a record from the default file. The record ;is identified by a 16-bit value which is expected to be in the first ;two bytes of the record. If the record is found, we will return a ;pointer to the first byte and the length in bytes. ; ; Usage: ; ; Macro: ; ; MOV #record.indicator,R0 ; JSR PC,DF.RD ; (Return) ; ; On return: ; If record found: ; ; R0/ Address of first byte of record (after our header info) ; R1/ Length of record (minus header) in bytes ; ; If record not found: ; ; R0/ 0 ; R1/ -1 ; ;-- .PSECT $CODE$, RO DF.RD:: TSTB DFLOPN ; File open? BEQ 80$ ; No, just say we couldn't find the record MOV #DF.RAB,R1 ; Point at RAB $REWIND R1 ; Back up to beginning of file $COMPARE #SU$SUC,STS,R1 ; Did it work? BNE 80$ ; No, punt ; Now read through the file until we find the record we want 20$: $GET R1 ; Read a record $COMPARE #SU$SUC,STS,R1 ; Get it? BNE 80$ ; No, must have hit eof CMP R0,DF.BUF ; Is this the record we want? BNE 20$ ; If not the right record, try the next ; Here when we have found the correct record. Set up the pointers to the ;users data MOVB DF.BUF+.DFOFS,R0 ; Get offset to first byte of user data ADD #DF.BUF,R0 ; Point to it MOVB DF.BUF+.DFRSZ,R1 ; And get the size of the data MOVB #1,DFLRCR ; Flag current record is real RTS PC ; And return ; Here if we could not find the record for some reason. Return the error ;indication to our caller, and remember that we have no current record. 80$: CLRB DFLRCR ; No current record CLR R0 ; No data to return MOV #-1,R1 ; . . . RTS PC ; Let caller worry about it .SBTTL DF.WT - Write a record to the default file ;++ ; This routine will write a record to the default file. The record ;is identified by a 16-bit value which will be written as the first ;two bytes of the record. ; ; Usage: ; ; Macro: ; ; MOV #record.indicator,R0 ; MOV #Record.address,R1 ; MOV #record.size,R2 ; JSR PC,DF.WT ; (Return) ; ;-- .PSECT $CODE$, RO DF.WT:: TSTB DFLOPN ; File open? BEQ 99$ ; No, just return JSR R1,$SAVE2 ; Save R1/R2 TSTB DFLRCR ; Check if current record data ok BEQ 30$ ; No, we must first find this record CMP R0,DF.BUF+.DFRTP ; Correct record? BNE 30$ ; No, attempt to read it first ; Here if last record read is the one we wish to replace. First we must ;copy the users data into our buffer, then we will just update the current ;record in the file 10$: MOV R2,DF.BUF+.DFRSZ ; Store new record size MOVB #.DFHLN,DF.BUF+.DFOFS ; Store offset to record data MOV #DF.BUF+.DFHLN,R0 ; Point at data storage 20$: MOVB (R1)+,(R0)+ ; Copy the data SOB R2,20$ ; All of it MOV #DF.RAB,R0 ; Point at the RAB $STORE #DF.MRS,RSZ,R0 ; Store the record size $UPDATE R0 ; Update the record RTS PC ; And return ; Here if the last record was not valid or was not the same as the ;record being written. First attempt to find the correct record. If ;we can find it, we will just update it in place, otherwise, we will ;write the new record at the end of the file. 30$: MOV R0,-(SP) ; Save the record index MOV R1,-(SP) ; And the address JSR PC,DF.RD ; Attempt to find the record TST R1 ; See if we found it BMI 40$ ; If negative, no luck MOV (SP)+,R1 ; Get back the address MOV (SP)+,R0 ; and the type BR 10$ ; And re-write the record ; Here if the record did not previously exist in the file. Write ;it out at the end of the file. The next-record context should be EOF, since ;DF.RD will have read to the end of the file. 40$: MOV (SP)+,R1 ; Restore the registers MOV (SP)+,R0 ; . . . MOV R0,DF.BUF+.DFRTP ; Store the record type MOVB R2,DF.BUF+.DFRSZ ; And size MOVB #.DFHLN,DF.BUF+.DFOFS ; And offset to data portion MOV #DF.BUF+.DFHLN,R0 ; Point at first data byte 50$: MOVB (R1)+,(R0)+ ; Copy the byte SOB R2,50$ ; All of them MOV #DF.RAB,R0 ; Point at RAB $STORE #DF.MRS,RSZ,R0 ; Store the record size $PUT R0 ; Write the record 99$: RTS PC ; And return .SBTTL End of KERDF .END