.TITLE CONTIGUIZE - COPY A FILE AND MAKE IT CONTIGUOUS .IDENT /1.8/ ; ; AUTHOR: ROGER JENKINS ; DATE: 10/8/85 ; ;***************************************************************** ; ; RABS AND FABS ; ;***************************************************************** .PSECT FABS,WRT,NOEXE,LONG ;***************************************************************** ; ; INPUT FILE CONTROL BLOCKS ; ;***************************************************************** INFAB: $FAB FAC=,- NAM=INNAM INRAB: $RAB BKT=0,- FAB=INFAB,- MBC=51,- ROP=,- UBF=IO_BUF,- USZ=BUF_SIZE INNAM: $NAM ESA=EXPANDED_FILE_SPEC,- ESS=255,- RSA=EXPANDED_FILE_SPEC,- RSS=255 EXPANDED_FILE_SPEC: ; EXPANDED FILE SPEC WILL BE PLACED HERE .BLKB 255 ;***************************************************************** ; ; OUTPUT FILE ACCESS BLOCK (FAB) AND RECORD ACCESS BLOCK (RAB) ; ;***************************************************************** .ALIGN LONG OUTFAB: $FAB FAC=,- FOP= OUTRAB: $RAB BKT=0,- FAB=OUTFAB,- RBF=IO_BUF,- ROP= ;***************************************************************** ; ; PARSER DATA ; ;***************************************************************** .PSECT $TPADEF ; PARSER OFFSETS LF = 10 ; LINE FEED CHARACTER ALLOCATE_VALUE: .BLKL 1 ; NUMBER OF BLOCKS TO ALLOCATE SHOW_FLAG: .LONG 0 ; 1 IF SHOW SWITCH PRESENT INPUT_FILE_DESCR: .QUAD 0 ; DESCRIPTOR OF INPUT FILE OUTPUT_FILE_DESCR: .QUAD 0 ; DESCRIPTOR OF OUTPUT FILE ARG_BLK: .LONG TPA$K_COUNT0 ; LENGTH OF TABLE IN LONG WORDS .LONG TPA$V_ABBRFM ; ALLOW KEYWORD ABBREVIATIONS CMD_LEN: .BLKL 1 ; LENGTH OF CMD IN CMD_LINE .ADDRESS CMD_LINE ; COMMAND LINE ADDRESS .BLKB TPA$K_LENGTH0-16 ; REST OF BLOCK ;***************************************************************** ; ; PARSER STATE TABLE ; ;***************************************************************** $INIT_STATE STATE_TABLE,KEY_TABLE ; ; START SWITCHES AND/OR INPUT FILE SPEC ; $STATE START $TRAN TPA$_BLANK,START $TRAN '/',SWITCH_NAME $TRAN TPA$_LAMBDA,INPUT_FILE $STATE SWITCH_NAME $TRAN 'ALLOCATE',ALLOCATE_SWITCH $TRAN 'SHOW_COUNT',START,,1,SHOW_FLAG $STATE ALLOCATE_SWITCH $TRAN '=' $STATE $TRAN TPA$_DECIMAL,START,,,ALLOCATE_VALUE ; ; PARSE INPUT FILE NAME ; $STATE INPUT_FILE $TRAN TPA$_FILESPEC,,,,INPUT_FILE_DESCR ; ; PARSE OUTPUT FILE NAME $STATE $TRAN TPA$_FILESPEC,,,,OUTPUT_FILE_DESCR $TRAN TPA$_EOS,TPA$_EXIT $END_STATE ;***************************************************************** ; ; OTHER DATA ; ;***************************************************************** BUF_SIZE = 512*127 ; LARGEST NUMBER OF BLOCKS WE CAN XFR IO_BUF: .BLKB BUF_SIZE ; I/O BUFFER SIZE_GOAL: ; DESIRED SIZE OF OUTPUT FILE .BLKL 1 CUR_SIZE: ; CURRENT SIZE .LONG 0 CONTIG_SIZE: ; LARGEST CONTIGUOUS PEICE OF DISK .BLKL 1 EXT_NUM: ; CURRENT EXTENT NUMBER .LONG 0 BLOCKS_COPIED: ; NUMBER OF BLOCKS COPIED .LONG 0 CMD_LINE_DESCR: ; DESCR OF BLANK COMMAND LINE .LONG 256 .ADDRESS CMD_LINE CMD_LINE: ; CMD LINE BUFFER .BLKB 256 DISK: .LONG 0 ; DISK NAME DESCR .ADDRESS EXPANDED_FILE_SPEC PROMPT: .ASCID "File: " ; PROMPT TEXT PROMPT_FLAG: ; TO PROMPT OR NOT TO PROMPT .BLKL 1 SYNTAX_ERROR: .ASCID "***** Command line syntax error *****" NO_INPUT_FILE_MSG: .ASCID "***** No input file specified on command line *****" ALQ_MSG: .ASCID "File allocation beginning..." EXT_CTL: .ASCID "Extent # !UL contains !UL block!%S, total size: !UL block!%S" COPY_MSG: .ASCID "File copy beginning..." COPY_CTL: .ASCID "!6UL block!%S copied" DONE_MSG: .ASCID "All Done!!" BIGCONTIG_ERR_MSG: .ASCID "Error occured while allocating space:" FAO_BUF_DESCR: ; DESCRIPTION OF EMPTY BUFFER .LONG 80 .ADDRESS FAO_BUF FAO_BUF: ; BUFFER USED BY FAO .BLKB 80 FORMATTED_BUF_DESCR: ; DESC OF FORMATTED BUFFER .BLKL 1 .ADDRESS FAO_BUF ;***************************************************************** ; ; CODE ; ;***************************************************************** .ENTRY CONTIGUIZE,^M<> ;***************************************************************** ; ; GET FILE NAME FROM EITHER COMMAND LINE OR PROMPT ; ;***************************************************************** PROMPT_AGAIN: PUSHAL PROMPT_FLAG PUSHAL CMD_LEN PUSHAQ PROMPT PUSHAQ CMD_LINE_DESCR CALLS #4,G^LIB$GET_FOREIGN BLBS R0,GOT_COMMAND CMPL R0,#RMS$_EOF ; ^Z? BNEQ GET_CMD_ERROR ; NO BRW DONE ; YES - EXIT GET_CMD_ERROR: PUSHL R0 ; NO - PUSH ERORR STATUS CALLS #1,G^LIB$SIGNAL ; PRINT ERROR MESSAGE BRW DONE ; EXIT GOT_COMMAND: ;***************************************************************** ; ; PARSE COMMAND LINE ; ;***************************************************************** PUSHAL KEY_TABLE PUSHAL STATE_TABLE PUSHAL ARG_BLK CALLS #3,G^LIB$TPARSE ; PARSE COMMAND LINE BLBS R0,CHECK_PARSE ; CMD LINE PARSED OK MOVAQ SYNTAX_ERROR,R1 ; ADR OF ERROR MESSAGE BRW PARSE_ERROR ; CMD LINE HAD SYNTAX ERROR ;***************************************************************** ; ; SEE IF RESULTS OF THE PARSE ARE OK. ; SET UP POINTERS FOR OUTPUT FILE NAME. ; ;***************************************************************** CHECK_PARSE: TSTL INPUT_FILE_DESCR+4 ; IS DESCRIPTOR ADDRESS ZERO? BNEQ GOT_INPUT_FILE ; NO - ALL IS WELL MOVAQ NO_INPUT_FILE_MSG,R1 ; GET ADDRESS OF ERROR MSG BRW PARSE_ERROR ; WRITE ERROR MESSAGE GOT_INPUT_FILE: MOVL INPUT_FILE_DESCR+4,INFAB+FAB$L_FNA ; PUT FILE NAME ADR IN FAB CVTWB INPUT_FILE_DESCR,INFAB+FAB$B_FNS ; PUT FILE NAME LEN IN FAB MOVL INPUT_FILE_DESCR+4,OUTFAB+FAB$L_DNA ; PUT FILE NAME ADR IN FAB CVTWB INPUT_FILE_DESCR,OUTFAB+FAB$B_DNS ; PUT FILE NAME LEN IN FAB TSTL OUTPUT_FILE_DESCR ; IS DESCRIPTOR ADDRESS ZERO? BEQL NO_OUTPUT_FILE ; YES - USE INPUT AS DEFAULT MOVL OUTPUT_FILE_DESCR+4,OUTFAB+FAB$L_FNA ; PUT FILE NAME ADR IN FAB CVTWB OUTPUT_FILE_DESCR,OUTFAB+FAB$B_FNS ; PUT FILE NAME LEN IN FAB NO_OUTPUT_FILE: ;***************************************************************** ; ; OPEN AND CONNECT TO INPUT FILE. ; ;***************************************************************** $OPEN FAB=INFAB ; OPEN INPUT FILE BLBS R0,CON_IN ; OK BRW IN_FAB_ERROR ; ERROR CON_IN: $CONNECT RAB=INRAB ; CONNECT RECORD STREAM BLBS R0,FAB_COPY ; OK BRW IN_RAB_ERROR ; ERROR ;***************************************************************** ; ; BUILD DISK DESCRIPTOR FROM INNAM. ; MOVE VALUES INTO OUTFAB. MOST COME FROM INFAB, BUT ALLOCATION ; QUANTITY WILL COME FROM COMMAND LINE IF /ALLOCATE= WAS ; SPECIFIED. ;***************************************************************** FAB_COPY: MOVB INNAM+NAM$B_ESL,DISK ; ASSUME ESL FOR NOW TSTB INNAM+NAM$B_RSL ; IS RSL THE ONE TO USE? BEQL NOT_RSL ; NO - KEEP WHAT WE GOT MOVB INNAM+NAM$B_RSL,DISK ; YES - USE RSL NOT_RSL: MOVL INFAB+FAB$L_ALQ,SIZE_GOAL ; FILE SIZE TSTL ALLOCATE_VALUE ; ALQ FROM CMD LINE? BEQL NO_ALQ_VALUE ; NO MOVL ALLOCATE_VALUE,SIZE_GOAL ; YES - PUT IT IN FAB NO_ALQ_VALUE: MOVB INFAB+FAB$B_BKS,OUTFAB+FAB$B_BKS ; BUCKET SIZE MOVW INFAB+FAB$W_DEQ,OUTFAB+FAB$W_DEQ ; DEFAULT EXTEND SIZE MOVB INFAB+FAB$B_FSZ,OUTFAB+FAB$B_FSZ ; FIXED CTRL AREA SIZE MOVW INFAB+FAB$W_GBC,OUTFAB+FAB$W_GBC ; GLOBAL BUFFER COUNT MOVL INFAB+FAB$L_MRN,OUTFAB+FAB$L_MRN ; MAX RECORD NUMBER MOVW INFAB+FAB$W_MRS,OUTFAB+FAB$W_MRS ; MAX RECORD SIZE MOVB INFAB+FAB$B_ORG,OUTFAB+FAB$B_ORG ; FILE ORGANIZATION MOVB INFAB+FAB$B_RAT,OUTFAB+FAB$B_RAT ; RECORD ATTRIBUTES MOVB INFAB+FAB$B_RFM,OUTFAB+FAB$B_RFM ; RECORD FORMAT ;***************************************************************** ; ; PRINT STARTING MESSAGE ; FIND OUT SIZE OF LARGEST CONTIGUOUS PIECE ; MOVE SIZE INTO FAB ; ;***************************************************************** TSTL SHOW_FLAG ; DO THEY WANT TO SEE MESSAGES? BEQL NO_SHOW_ALQ ; NO, SO DON'T PRINT THEM PUSHAQ ALQ_MSG ; "STARTING ALLOCATION" MESSAGE CALLS #1,G^LIB$PUT_OUTPUT ; PRINT IT NO_SHOW_ALQ: PUSHAL CONTIG_SIZE ; RETURN BIGGEST CONTIG PIECE HERE PUSHAQ DISK ; DISK WHERE OUTPUT FILE WILL BE PLACED CALLS #2,BIGCONTIG ; FIND LARGEST CONTIGOUS PIECE BLBS R0,NO_CREATE_ALQ_ERROR ; NO ERROR FROM BIGCONTIG BRW BIGCONTIG_ERROR ; ERROR FROM BIGCONTIG NO_CREATE_ALQ_ERROR: MOVL CONTIG_SIZE,OUTFAB+FAB$L_ALQ ; MAKE FAB SIZE = BIG PIECE CMPL CONTIG_SIZE,SIZE_GOAL ; IS CONTIGUOUS PIECE TOO BIG? BLEQ CREATE ; NO - OK TO CREATE MOVL SIZE_GOAL,OUTFAB+FAB$L_ALQ ; YES - ONLY USE WHAT WE NEED ;***************************************************************** ; ; CREATE OUTPUT FILE ; ;***************************************************************** CREATE: $CREATE FAB=OUTFAB ; OPEN OUTPUT FILE BLBS R0,CON_OUT ; NO ERRORS BRW OUT_FAB_ERROR ; ERROR CON_OUT: $CONNECT RAB=OUTRAB ; CONNECT TO RECORD STREAM BLBS R0,EXTEND_PREP ; NO ERRORS BRW OUT_RAB_ERROR ; ERROR ;***************************************************************** ; ; EXTEND FILE UNTIL IT REACHES ITS DESIRED SIZE ; ;***************************************************************** EXTEND_PREP: ADDL2 OUTFAB+FAB$L_ALQ,CUR_SIZE ; COMPUTE CURRENT FILE SIZE TSTL SHOW_FLAG ; DO THEY WANT TO SEE MESSAGES? BEQL NO_SHOW_EXT ; NO, SO DON'T PRINT THEM INCL EXT_NUM ; COUNT THIS EXTENT $FAO_S CTRSTR=EXT_CTL,- ; FORMAT EXTEND MESSAGE OUTLEN=FORMATTED_BUF_DESCR,- OUTBUF=FAO_BUF_DESCR,- P1=EXT_NUM,- P2=OUTFAB+FAB$L_ALQ,- P3=CUR_SIZE PUSHAQ FORMATTED_BUF_DESCR ; ADR OF LINE TO BE PRINTED CALLS #1,G^LIB$PUT_OUTPUT ; WRITE OUTPUT NO_SHOW_EXT: CMPL CUR_SIZE,SIZE_GOAL ; HAVE WE REACHED OUR DESIRED SIZE? BGEQ COPY_BLOCK ; YES - START COPYING BLOCKS PUSHAL CONTIG_SIZE ; LARGEST CONTIGUOUS PIECE PUSHAL DISK ; DISK CONTAINING OUTPUT FILE CALLS #2,BIGCONTIG ; FIND LARGEST CONTIGOUS PIECE BLBS R0,NO_EXT_ALQ_ERROR ; NO ERROR FROM BIGCONTIG BRW BIGCONTIG_ERROR ; ERROR FROM BIGCONTIG NO_EXT_ALQ_ERROR: MOVL CONTIG_SIZE,OUTFAB+FAB$L_ALQ ; GET ALL OF THE CONTIG SPACE ADDL3 CONTIG_SIZE,CUR_SIZE,R9 ; COMPUTE TOTAL FILE SIZE CMPL R9,SIZE_GOAL ; WILL IT BE TOO BIG? BLEQ EXTEND ; NO - OK TO EXTEND SUBL3 CUR_SIZE,SIZE_GOAL,OUTFAB+FAB$L_ALQ ; YES - ONLY USE WHAT WE NEED EXTEND: $EXTEND FAB=OUTFAB ; EXTEND THE FILE BRW EXTEND_PREP ; GO BACK AND SEE IF WE NEED MORE ;***************************************************************** ; ; COPY BLOCK BY BLOCK ; ;***************************************************************** COPY_BLOCK: TSTL SHOW_FLAG ; DO THEY WANT TO SEE MESSAGES? BEQL COPY_NEXT_BLOCK ; NO, SO DON'T PRINT THEM PUSHAQ COPY_MSG ; COPY STARTING MESSAGE CALLS #1,G^LIB$PUT_OUTPUT ; PRINT MESSAGE ;***************************************************************** ; ; READ A BUFFER OF DATA ; ;***************************************************************** COPY_NEXT_BLOCK: $READ RAB=INRAB ; READ A BLOCK BLBS R0,WRITE ; READ WAS OK CMPL R0,#RMS$_EOF ; EOF? BEQL DONE ; YES - STOP BRW IN_RAB_ERROR ; AN ERROR OCCURED ;***************************************************************** ; ; WRITE BUFFER OF DATA ; ;***************************************************************** WRITE: MOVW INRAB+RAB$W_RSZ,OUTRAB+RAB$W_RSZ ; MOVE REC SIZE TO OUTRAB $WRITE RAB=OUTRAB ; WRITE BLOCK BLBS R0,NO_WRITE_ERROR ; NO ERROR BRW OUT_RAB_ERROR ; ERROR - GO TO ERROR SECTION ;***************************************************************** ; ; SEE IF WE PRINT NUMBER OF BLOCKS COPIED, ; COMPUTE NUMBER OF BLOCKS COPIED ; FORMAT AND PRINT MESSAGE ; GO BACK FOR MORE ; ;***************************************************************** NO_WRITE_ERROR: TSTL SHOW_FLAG ; DO THEY WANT TO SEE MESSAGES? BEQL NO_SHOW_COPY_BLOCK ; NO, SO DON'T PRINT THEM MOVZWL INRAB+RAB$W_RSZ,R9 ; GET NUMBER OF BYTES READ DIVL2 #512,R9 ; CONVERT BYTES TO BLOCKS ADDL2 R9,BLOCKS_COPIED ; COUNT TOTAL BLOCKS COPIED $FAO_S CTRSTR=COPY_CTL,- ; FORMAT COPY MESSAGE OUTLEN=FORMATTED_BUF_DESCR,- OUTBUF=FAO_BUF_DESCR,- P1=BLOCKS_COPIED PUSHAQ FORMATTED_BUF_DESCR ; ADR OF LINE TO BE PRINTED CALLS #1,G^LIB$PUT_OUTPUT ; WRITE OUTPUT NO_SHOW_COPY_BLOCK: BRW COPY_NEXT_BLOCK ; COPY ANOTHER MOUTHFULL ;***************************************************************** ; ; WRAP THINGS UP ; ;***************************************************************** DONE: TSTL SHOW_FLAG ; DO THEY WANT TO SEE MESSAGES? BEQL NO_SHOW_DONE ; NO, SO DON'T PRINT THEM PUSHAQ DONE_MSG ; ADR OF DONE MESSAGE CALLS #1,G^LIB$PUT_OUTPUT ; WRITE OUTPUT NO_SHOW_DONE: $CLOSE FAB=INFAB ; CLOSE INPUT FILE $CLOSE FAB=OUTFAB ; CLOSE OUTPUT FILE BRB EXIT ;***************************************************************** ; ; ERROR PROCESSING ; ;***************************************************************** IN_FAB_ERROR: MOVL INFAB+FAB$L_STS,R2 ; ERROR STATUS CODE MOVL INFAB+FAB$L_STV,R3 ; ERROR STATUS VECTOR BRB WRITE_IO_ERROR_MSG ; NOW WRITE ERROR MESSAGE IN_RAB_ERROR: MOVL INRAB+RAB$L_STS,R2 ; ERROR STATUS CODE MOVL INRAB+RAB$L_STV,R3 ; ERROR STATUS VECTOR BRB WRITE_IO_ERROR_MSG ; NOW WRITE ERROR MESSAGE OUT_FAB_ERROR: MOVL OUTFAB+FAB$L_STS,R2 ; ERROR STATUS CODE MOVL OUTFAB+FAB$L_STV,R3 ; ERROR STATUS VECTOR BRB WRITE_IO_ERROR_MSG ; NOW WRITE ERROR MESSAGE OUT_RAB_ERROR: MOVL OUTRAB+RAB$L_STS,R2 ; ERROR STATUS CODE MOVL OUTRAB+RAB$L_STV,R3 ; ERROR STATUS VECTOR BRB WRITE_IO_ERROR_MSG ; NOW WRITE ERROR MESSAGE WRITE_IO_ERROR_MSG: PUSHL R3 ; PUSH STATUS VECTOR ONTO STACK PUSHL R2 ; PUSH STATUS CODE ONTO STACK CALLS #2,G^LIB$SIGNAL ; WRITE ERROR MESSAGE BRB EXIT ; RETURN TO CALLER PARSE_ERROR: PUSHL R1 ; ADR OF ERROR MESSAGE DESCRIPTOR CALLS #1,G^LIB$PUT_OUTPUT ; WRITE ERROR MESSAGE BRB EXIT ; RETURN TO CALLER BIGCONTIG_ERROR: PUSHL R0 ; SAVE ERROR CODE FOR LIB$SIGNAL PUSHAL BIGCONTIG_ERR_MSG ; MESSAGE ADR FOR LIB$PUT_OUTPUT CALLS #1,G^LIB$PUT_OUTPUT ; SAY ERROR IS FROM BIGCONTIG CALLS #1,G^LIB$SIGNAL ; WRITE ERROR MESSAGE BRB EXIT ; RETURN TO CALLER EXIT: RET ; RETURN TO CALLER (VMS) WITH STATUS .END CONTIGUIZE