.TITLE TYPE .IDENT /01-000/ ;++ ; ; Facility: TYPE ; ; Author: Hunter Goatley ; goathunter@WKUVX1.BITNET ; ; Date: November 15, 1992 ; ; Abstract: ; ; This program is a no-frills version of TYPE that shows ; some simple RMS calls to read a file. ; ; Modified by: ; ; 01-000 Hunter Goatley 15-NOV-1992 12:12 ; Original version. ; ;-- .DSABL GLOBAL ; Declare external references .ENABL SUPPRESSION ; Don't list unreference symbols .NOSHOW BINARY ; Include binary in listings ; ; External routines: ; .EXTRN LIB$GET_FOREIGN ; Get foreign command line .EXTRN LIB$PUT_OUTPUT ; Write to SYS$OUTPUT $DSCDEF ; Descriptor symbols $SSDEF ; System service status symbols $FABDEF ; Define FAB symbols $RABDEF ; Define RAB symbols $RMSDEF ; RMS status symbols .SHOW BINARY ; Include binary in listings .PSECT _TYPE_DATA,NOEXE,WRT,LONG,SHR INPUT_FAB: $FAB DNM=,- ; The default name FAC=GET,- ; Want to GET from file SHR= ; Let others access it INPUT_RAB: $RAB FAB=INPUT_FAB,- ; Point to FAB RAC=SEQ,- ; Sequential access UBF=BUFFER,- ; Input buffer addr USZ=512 ; Size of input buffer BUFFER: .BLKB 512 ; Decent-sized buffer .ALIGN LONG ; Align on longword boundary GET_FOREIGN_ARGS: ; LIB$GET_FOREIGN arglst .LONG 3 ; ... 3 arguments .ADDRESS FILENAME ; ... The input buffer .ADDRESS 10$ ; ... The prompt .ADDRESS FILENAME ; ... Word to receive length 10$: .ASCID /_File: / ; Foreign command prompt FILENAME: .WORD 0 ; Dynamic descriptor for string .BYTE DSC$K_DTYPE_T ; ... Text string .BYTE DSC$K_CLASS_D ; ... Dynamic string .LONG 0 ; ... Address filled in later OUTBUFF_D: .WORD 0 ; Static descriptor for string .BYTE DSC$K_DTYPE_T ; ... Text string .BYTE DSC$K_CLASS_S ; ... Static string .LONG 0 ; ... Address filled in later .PSECT _TYPE_CODE,EXE,NOWRT,LONG,PIC,SHR .ENTRY TYPE,^M ; ; Call LIB$GET_FOREIGN to get the filename ; CALLG GET_FOREIGN_ARGS,- ; Get the filename to TYPE G^LIB$GET_FOREIGN ; ... BLBC R0,40$ ; Branch on error ; ; See if a filename was even given. ; MOVAQ FILENAME,R1 ; R1 -> filename descriptor MOVL #SS$_NORMAL,R0 ; Assume normal status TSTW DSC$W_LENGTH(R1) ; Was there a length? BEQLU 40$ ; If no filename, just exit ; ; Now make the FAB point to the filename using $FAB_STORE. The FAB and ; RAB addresses are copied to registers for efficiency. ; MOVAL INPUT_FAB,R2 ; Move FAB address to R2 MOVAL INPUT_RAB,R3 ; Move RAB address to R3 $FAB_STORE - ; Store the necessary FAB info FAB = (R2),- ; ... The FAB address FNA = @DSC$A_POINTER(R1),- ; ... The filename address FNS = DSC$W_LENGTH(R1) ; ... The filename length ; ; Now open the file using $OPEN ; $OPEN FAB=(R2) ; Try to open the file BLBC R0,40$ ; Branch on error ; ; Now connect the RAB to the open file ; $CONNECT - ; Connect the RAB to the file RAB=(R3) ; ... BLBC R0,20$ ; Branch on error MOVAQ OUTBUFF_D,R4 ; R4 -> output descriptor PUSHL #SS$_NORMAL ; Push "normal" status on stack 10$: $GET RAB=(R3) ; Read a record from the file CMPL #RMS$_EOF,R0 ; Was EOF returned? BEQLU 30$ ; Branch if so BLBC R0,20$ ; Branch on any other error MOVW RAB$W_RSZ(R3),DSC$W_LENGTH(R4) ; Copy length to descriptor MOVL RAB$L_RBF(R3),DSC$A_POINTER(R4) ; Copy address to descriptor PUSHAQ (R4) ; Print the buffer to SYS$OUTPUT CALLS #1,G^LIB$PUT_OUTPUT ; ... BRB 10$ ; Loop until EOF 20$: MOVL R0,(SP) ; Replace "normal" with error 30$: $CLOSE FAB=(R2) ; Close the file POPL R0 ; Restore saved status 40$: RET ; Return to caller .END TYPE .TITLE COPY_FILE .IDENT /01-000/ ;++ ; ; Facility: COPY_FILE ; ; Author: Hunter Goatley ; goathunter@WKUVX1.BITNET ; Western Kentucky University ; ; Date: November 15, 1992 ; ; Abstract: ; ; This MACRO-32 module contains the routine COPY_FILE. It is ; provided as an example of calling RMS routines from MACRO-32 ; for the "MACRO Made Easy" series in _Digital Systems Journal_. ; ; Modified by: ; ; 01-000 Hunter Goatley 15-NOV-1992 15:48 ; Original version. ; ;-- .DSABL GLOBAL ; Declare external references .ENABL SUPPRESSION ; Don't list unreference symbols .NOSHOW BINARY ; Include binary in listings .MACRO ON_ERR THERE,?HERE BLBS R0,HERE ; Branch on success BRW THERE ; Branch to THERE on error HERE: .ENDM ON_ERR $DSCDEF ; Descriptor symbols $RMSDEF ; RMS status symbols $FABDEF ; Define FAB symbols $RABDEF ; Define RAB symbols $SSDEF ; System service status symbols MAX_REC_SIZE = 127*512 ; Read up to 127 blocks at once .SHOW BINARY ; Include binary in listings .PSECT _COPY_FILE_DATA,NOEXE,WRT,LONG ; ;*** File Access Block for input ; INFAB: $FAB FAC=,- ; File Access (Block I/O & GET) SHR= ; Allow others to read also ; ;*** Record Access Block for input ; INRAB: $RAB FAB=INFAB, - ; The File Access Block RAC=SEQ, - ; Record Access is sequential UBF=INREC, - ; Input buffer address USZ=MAX_REC_SIZE ; The max size of record ; ;*** File Access Block for output ; OUTFAB: $FAB FAC= ; File Access (Block I/O & PUT) ; ;*** Record Access Block for output ; OUTRAB: $RAB FAB=OUTFAB, - ; The File Access Block RAC=SEQ, - ; Record Access is sequential RBF=INREC ; The record buffer address .ALIGN LONG INREC: .BLKB MAX_REC_SIZE ; Input buffer .SBTTL COPY_FILE ;+ ; ; Routine: COPY_FILE ; ; Functional Description: ; ; This routine copies one file to another using RMS block I/O. ; The data in the file is copied intact, though not all file ; attributes are preserved; specifically, such things as creation ; date, backup date, protection, etc., are not maintained. ; ; NOTE: THIS ROUTINE MAKES SOME ASSUMPTIONS ABOUT THE PARAMETERS ; PASSED IN. IT ASSUMES THAT STRING DESCRIPTOR ADDRESSES ARE ; PASSED BY REFERENCE. ; ; Also, note that the source file name is used as the default ; file name of the copy. The new file will be created in the ; same directory as the existing file. ; ; Formal parameters: ; ; 4(AP) - Address of descriptor for the source file ; 8(AP) - Address of descriptor for the new file ; ; Returns: ; ; R0 - Status ; ;- OLD_FILE = 1*4 ; The original file name NEW_FILE = 2*4 ; The filename of the copy .PSECT _COPY_FILE_CODE,EXE,NOWRT,LONG,SHR .ENTRY COPY_FILE,^M MOVAB INFAB,R2 ; Move addresses to registers MOVAB OUTFAB,R3 ; ... for efficiency MOVAB INRAB,R4 ; ... MOVAB OUTRAB,R5 ; ... ; ; Initialize the file name in the original file's FAB. ; MOVQ @OLD_FILE(AP),R6 ; Get descriptor of file names MOVZBL R6,R6 ; Get the length as a byte $FAB_STORE - ; Store the filename in the FAB FAB=(R2), - ; ... FNA=(R7), - ; ... FNS=R6 ; ... ; ; Copy the name to the new file's FAB as the default name to allow ; default fields to be applied, ; $FAB_STORE - ; Store the filename in the FAB FAB=(R3), - ; ... Use for the default DNA=(R7), - ; ... file spec for the target DNS=R6 ; ... (for wildcarding) ; ; Now store the new filename in the FAB. ; MOVQ @NEW_FILE(AP),R6 ; Get descriptor for new name MOVZBL R6,R6 ; Get the length as a byte $FAB_STORE - ; Store the filename in the FAB FAB=(R3), - ; ... FNA=(R7), - ; ... FNS=R6 ; ... ; ; Open the original file for reading. ; $OPEN FAB=(R2) ; Open the input file ON_ERR 50$ ; Branch on error $CONNECT RAB=(R4) ; Connect the RAB to it ON_ERR 50$ ; Branch on error ; ; The file is open, so copy the fields related to organization, type, ; size, etc., to the FAB for the new file. ; MOVL FAB$L_ALQ(R2),FAB$L_ALQ(R3) ; Copy the Allocation size MOVW FAB$B_BKS(R2),FAB$B_BKS(R3) ; Copy the bucket size MOVL FAB$L_MRN(R2),FAB$L_MRN(R3) ; Copy the maximum record # MOVW FAB$W_MRS(R2),FAB$W_MRS(R3) ; Copy the Maximum Record Size MOVB FAB$B_ORG(R2),FAB$B_ORG(R3) ; Copy the file ORGanization MOVB FAB$B_RAT(R2),FAB$B_RAT(R3) ; Copy the Record ATtributes MOVB FAB$B_RFM(R2),FAB$B_RFM(R3) ; Copy the Record ForMat ; ; Now create the new file using the $CREATE service. ; $CREATE FAB=(R3) ; Open the same file for output ON_ERR 50$ ; Branch on error PUSHL #SS$_NORMAL ; Save "normal" status on stack $CONNECT RAB=(R5) ; Connect ON_ERR 30$ ; Branch on error ; ; The SS$_NORMAL is still on top of the stack to be used when EOF is reached. ; ; Multiple blocks are read with each $READ and written with each $WRITE. ; ; 10$: $READ RAB=(R4) ; Read a block of the file CMPL #RMS$_EOF,R0 ; End of file? BEQLU 40$ ; Branch if so BLBC R0,30$ ; Success? Go on 20$: MOVW RAB$W_RSZ(R4),RAB$W_RSZ(R5) ; Move the size to the OUTRAB $WRITE RAB=(R5) ; Write the modified record out BLBC R0,30$ ; Error? Return it BRB 10$ ; Go get next record and process it ; 30$: MOVL R0,(SP) ; Save the error status 40$: $CLOSE FAB=(R3) ; Close the file POPL R0 ; Restore the status 50$: PUSHL R0 ; Save the status $CLOSE FAB=(R2) ; Close the input file POPL R0 ; Restore the status RET ; Return to the caller .END /* * File: COPY.C * * Author: Hunter Goatley, goathunter@WKUVX1.BITNET * * Date: November 15, 1992 * * Abstract: * * Incredibly simplistic C program that copies one file to another * by calling the MACRO-32 routine COPY_FILE. * */ #include extern COPY_FILE(); int main(int argc, char *argv[]) { struct dsc$descriptor_s infile = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; struct dsc$descriptor_s outfile = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; if (argc != 3) { /* Simple error check */ printf("Usage: copy old-file new-file\n"); return(1); } /* Initialize the string descriptors using the (expected) arguments */ infile.dsc$w_length = strlen(argv[1]); infile.dsc$a_pointer = argv[1]; outfile.dsc$w_length = strlen(argv[2]); outfile.dsc$a_pointer = argv[2]; /* Now copy the file */ return (COPY_FILE (&infile, &outfile)); } Record Management Services $CLOSE Close a file $CONNECT Connect a RAB to a file $CREATE Create a file $DELETE Delete a record in a file $DISCONNECT Disconnect a RAB from a file $DISPLAY Get file attribute information $ENTER Enter a file name into a directory $ERASE Delete a file and its directory entry $EXTEND Extend a file's size (allocate more blocks) $FIND Find a particular record in a file $FLUSH Flush all RMS buffers to disk $FREE Unlock all locked records $GET Get a record from a file $NXTVOL Process next tape volume $OPEN Open a file $PARSE Parse a filename $PUT Write a record to a file $READ Read a block from a file (block I/O) $RELEASE Unlock the current record $REMOVE Remove a file's directory entry $RENAME Rename a file $REWIND Position file pointer to first record $SEARCH Search for one or more files $SPACE Move forward or backward X blocks $TRUNCATE Remove records from the end of a file $UPDATE Update a record in an indexed file $WAIT Wait for asynchronous RMS I/O $WRITE Write a block to a file (block I/O) Storage macros $FAB Define a File Access Block $RAB Define a Record Access Block $NAM Define a NAM block for name processing $XABALL Controls disk space allocation $XABDAT Provides file date information $XABFHC Provides file header information $XABJNL Provides journaling information $XABKEY Provides additional key information $XABPRO Provides control over file protection $XABRDT Provides revision-date information $XABSUM Provides summary information $XABTRM Controls RMS terminal I/O