home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
bin
/
msvv90sea.exe
/
MSBOOFLS.EXE
/
MSBMKB.FOR
< prev
next >
Wrap
Text File
|
1992-07-30
|
12KB
|
325 lines
C PROGRAM BIN2BOO
C
C****** GISBERT W.SELKE (RECK@DBNUAMA1.BITNET), 05/11/87
C WISSENSCHAFTLICHES INSTITUT DER ORTSKRANKENKASSEN,
C KORTRIJKER STRASSE 1, D-5300 BONN 2, WEST GERMANY
C RECK@DBNUAMA1.BITNET
C
C BOOING PROGRAM IN FORTRAN IV
C
C THIS IS A UTILITY PROGRAMME TO CONVERT BINARY DATA INTO
C STANDARD ASCII TEXT IN ORDER TO FACILITATE DATA TRANSFER
C
C IT IS NOT MEANT TO BE A TRANSFER PROTOCOL REPLACEMENT; IT
C JUST MAKES TRANSFER POSSIBLE ACROSS LINES (E.G., DATA NETWORKS)
C WHEN NO KERMIT ARE AVAILABLE OR ONE OF THEM CAN'T COPE WITH
C BINARY STUFF.
C
C BEWARE OF GREMLINS, THOUGH; ESPECIALLY EBCDIC <-> ASCII
C TRANSLATION MAY BE A PROBLEM FOR SOME OF THE CHARACTERS ...
C
C BASICALLY, 3 BYTES = 24 BITS ARE ENCODED INTO 4 CHARACTERS
C BY DIVIDING THEM INTO 6-BIT-PIECES AND THEN ADDING ASCII-ZERO
C TO MAKE THESE PIECES PRINTABLE. THE RESULT LIES IN THE RANGE
C ASCII-ZERO TO ASCII-SMALL-O. - IN ADDITION, NULL COMPRESSION
C TAKES PLACE; CONSECUTIVE NULL BYTES (WHICH OCCUR FREQUENTLY
C IN EXECUTABLE FILES, E.G.) ARE ENCODED WITH A TILDE LEAD-IN
C FOLLOWED BY THE NUMBER OF NULLS (UP TO 78), AGAIN RENDERED
C PRINTABLE BY ADDING ASCII-ZERO. THE RESULTING CHARACTER IS IN
C THE RANGE ASCII-ZERO (WELL, ASCII-TWO OR -THREE, REALLY) TO
C TILDE (ASCII CODE 126). - CHUNKS OF FOUR CHARACTERS BELONGING
C TOGETHER (RSP. TILDE AND NULL REPEAT COUNT) SHOULD NOT BE
C DIVIDED ACROSS LINES. A LINE HAS A MAXIMUM LENGTH OF 76
C CHARACTERS. - IN ADDITION, THE FIRST LINE OF THE FILE CONTAINS
C THE NAME OF THE ORIGINAL FILE (IF KNOWN - OTHERWISE A DUMMY NAME)
C AND NOTHING ELSE.
C
C SIBLING PROGRAMMES TO DECODE BOO FORMAT EXIST IN A VARIETY OF
C LANGUAGES, MOST NOTABLY C, PASCAL, BASIC, AND FORTRAN, OF COURSE.
C
C THE BOO-FORMAT WAS DEVELOPPED FOR SAFE (WELL, NOT *REALLY* SAFE...)
C BOOTSTRAPPING PURPOSES DURING KERMIT EVOLUTION BY BILL CATCHINGS
C AND FRANK DA CRUZ OF COLUMBIA UNIVERSITY, OR SO I THINK.
C
C THANKS TO FRANK, BILL, DAPHNE AND MANY OTHER PEOPLE FOR ALL
C THEY'VE DONE TO MAKE LIFE EASIER!
C
C CERTAIN SYSTEM SPECIFIC FEATURES CANNOT BE AVOIDED; HENCE,
C YOU SHOULD CHECK THE CODE BELOW CAREFULLY. I HAVE TRIED TO
C INDICATE THE PLACES WHERE PROBLEMS ARE LIKELY TO OCCUR;
C THESE INCLUDE WORD-SIZE DEPENDANCIES AND THE WAY BINARY
C I/O (I.E., UNHAMPERED BY ANY CONTROL CHARACTERS) IS
C ACCOMPLISHED. ALSO, THE INPUT RECORD SIZE WILL NEED CHECKING.
C
C AS FAR AS POSSIBLE, PARAMETERS ARE SET IN DATA STATEMENTS IN
C THE SUBROUTINES TO WHICH THEY PERTAIN; I/O CHANNEL NUMBERS
C ARE ASSIGNED IN A DATA STATEMENT IN THE MAIN PROGRAMME (BELOW).
C
C IMPROVEMENTS ARE WELCOME AND SHOULD BE SENT EITHER DIRECTLY
C TO THE AUTHOR OR TO THE KERMIT MAINTAINERS AT COLUMBIA UNIVERSITY,
C NEW YORK, USA.
C
C PARAMETERS ARE SET AS FOLLOWS:
C INPUT : I/O UNIT 5; ASSUMED TO BE 256 BYTE RECORDS
C OUTPUT : I/O UNIT 7; PADDED WITH BLANKS TO YIELD 80 CHARACTERS ALWAYS
C CONTROL OUTPUT: I/O UNIT 6 (NOT REALLY NECESSARY)
C
C NO REWIND WILL BE PERFORMED ON EITHER INPUT OR OUTPUT BEFORE OR
C AFTER PROCESSING. OUTPUT FILE WILL HAVE A SINGLE FILE MARK AT END.
C
C ALL VARIABLES ARE ASSUMED TO BE 32-BIT-QUANTITIES
C
IMPLICIT INTEGER*4 (A-Z)
LOGICAL*4 ZFOUND,ZNULL
REAL*4 RATE
DIMENSION CHUNK(4),BYTES(3)
C INITIALIZATION OF SOME PSEUDO-CHARACTER CONSTANTS, EACH RIGHT-
C JUSTIFIED IN AN INTEGER VARIABLE:
C R6BITS HAS THE 6 RIGHT-MOST BITS SET; CZERO IS ASCII-0, AND
C CREP IS ASCII-TILDE:
DATA R6BITS/63/, CZERO/48/, CREP/126/
DATA LMAX/78/, NULL/0/, TWO/2/, FOUR/4/
C --- I/O UNITS:
DATA INPUT/5/, OUTPUT/7/, CONTRL/6/
C
C --- INITIALISATION:
INCT = 0
INBYTE = 0
INPT = 0
NULLCT = 0
ZFOUND = .TRUE.
WRITE (CONTRL,10000)
10000 FORMAT (//' Conversion from binary to boo format starts.'/)
CALL WRINI(OUTPUT,OUTCT,OUTCHR,OUTPT)
10 CONTINUE
C --- MAIN INPUT LOOP:
C --- ASSEMBLE 3 BYTES:
CALL GETBYT(BYTES(1),INPUT,INCT,INBYTE,INPT,CONTRL,ZFOUND)
IF (.NOT.ZFOUND) GOTO 200
12 ZNULL = BYTES(1).EQ.NULL
CALL GETBYT(BYTES(2),INPUT,INCT,INBYTE,INPT,CONTRL,ZFOUND)
ZNULL = ZNULL .AND. BYTES(2).EQ.NULL
CALL GETBYT(BYTES(3),INPUT,INCT,INBYTE,INPT,CONTRL,ZFOUND)
ZNULL = ZNULL .AND. BYTES(3).EQ.NULL
15 CONTINUE
IF (.NOT.ZNULL) GOTO 30
C --- START NULL COMPRESSION:
I = 3
20 CONTINUE
I = I + 1
CALL GETBYT(BYTES(1),INPUT,INCT,INBYTE,INPT,CONTRL,ZFOUND)
IF ((BYTES(1).EQ.NULL) .AND. ZFOUND .AND. (I.LE.LMAX)) GOTO 20
C --- END OF NULL SEQUENCE:
I = I - 1
NULLCT = NULLCT + I
CHUNK(1) = CREP
CHUNK(2) = I + CZERO
CALL WRCHAR(CHUNK,OUTPUT,OUTCT,OUTCHR,OUTPT,TWO)
IF (ZFOUND) GOTO 12
GOTO 200
30 CONTINUE
C --- NON-NULL BYTES; SHIFT BITS TO FORM CHUNK:
CHUNK(1) = ISHFT(BYTES(1),-2) + CZERO
CHUNK(2) = IAND(IOR(ISHFT(BYTES(1),4),ISHFT(BYTES(2),-4)),
* R6BITS) + CZERO
CHUNK(3) = IAND(IOR(ISHFT(BYTES(2),2),ISHFT(BYTES(3),-6)),
* R6BITS) + CZERO
CHUNK(4) = IAND(BYTES(3),R6BITS) + CZERO
CALL WRCHAR(CHUNK,OUTPUT,OUTCT,OUTCHR,OUTPT,FOUR)
IF (ZFOUND) GOTO 10
200 CONTINUE
C --- END OF FILE; FLUSH OUTPUT BUFFER BY PADDING WITH BLANKS:
CALL FLSHSO(OUTPUT,OUTCT,OUTPT)
RATE = 0.0
IF (OUTCHR.GT.0) RATE = (100.0*INBYTE) / OUTCHR
WRITE (CONTRL,19000) INCT,INBYTE,OUTCT,OUTCHR,NULLCT,RATE
19000 FORMAT (//' Number of input sectors:',I9,
* '; number of input bytes:',I9
* /' Number of output lines :',I9,
* '; number of output chars:',I9
* /' Number of nulls :',I9,
* '; efficiency :',F8.1,'%'/)
STOP
END
C
C
SUBROUTINE WRCHAR(CHUNK,OUTPUT,OUTCT,OUTCHR,OUTPT,NBR)
C
C OUTPUT NBR CHARACTERS (CHUNK) TO OUTPUT;
C UPDATE LINES WRITTEN (OUTCT), CHARS WRITTEN (OUTCHR),
C POINTER TO OUTPUT LINE (OUTPT)
C
C CALL WRINI FIRST FOR INITIALISATION.
C CALL FLSHSO FOR FINISHING OFF.
C
IMPLICIT INTEGER*4 (A-Z)
DIMENSION CHUNK(1),OUTLIN(20),DUMNAM(3)
C MAXLGT IS MAXIMUM NUMBER OF CHARACTERS ALLOWED; LINLEN IS
C NUMBER OF 32-BIT-WORDS ACTUALLY WRITTEN (DIMENSION OF OUTLIN):
DATA MAXLGT/76/, LINLEN/20/
C CBLANK IS ASCII-BLANK, RIGHT-JUSTIFIED, BLANK4 IS 4 BYTES BLANK:
DATA CBLANK/32/, BLANK4/' '/
C --- SOME FORTRANS HAVE NO WAY OF KNOWING EXTERNAL FILES NAMES,
C HENCE SUPPLY DUMMY NAME:
DATA DUMNAM/'BINA','RY.D','AT '/
C
C --- IS BUFFER FULL?
IF (OUTPT+NBR.LE.MAXLGT) GOTO 10
C --- BUFFER IS INDEED FULL; PAD TO BUFFER LENGTH AND PUT IT OUT:
K = 4*LINLEN - 1
DO 5 I=OUTPT,K
5 CALL INSRCH(CBLANK,OUTLIN,I+1)
WRITE (OUTPUT,40000) OUTLIN
C --- ADAPT IF NECESSARY:
40000 FORMAT (20A4)
OUTCT = OUTCT + 1
OUTPT = 0
10 CONTINUE
C --- PUT IN CHARACTERS:
DO 20 I=1,NBR
OUTPT = OUTPT + 1
OUTCHR = OUTCHR + 1
CALL INSRCH(CHUNK(I),OUTLIN,OUTPT)
20 CONTINUE
GOTO 90
C
C ENTRY WRINI:
C
ENTRY WRINI(OUTPUT,OUTCT,OUTCHR,OUTPT)
C
C --- ALL INITIALIZATIONS NEEDED FOR THE OUTPUT FILE GO HERE:
C --- WRITE DUMMY FILE NAME TO OUTPUT FILE, SINCE WE DON'T KNOW BETTER:
DO 30 I=1,3
30 OUTLIN(I) = DUMNAM(I)
K = 4*LINLEN
DO 35 I=13,K
35 CALL INSRCH(CBLANK,OUTLIN,I)
WRITE (OUTPUT,40000) OUTLIN
OUTCT = 0
OUTCHR = 0
OUTPT = 0
GOTO 90
C
C --- ENTRY FLSHSO:
C
ENTRY FLSHSO(OUTPUT,OUTCT,OUTPT)
C
C --- ANYTHING TO CLOSE THE OUTPUT FILE GOES HERE:
K = 4*LINLEN - 1
DO 50 I=OUTPT,K
50 CALL INSRCH(CBLANK,OUTLIN,I+1)
C --- WRITE THE REST:
WRITE (OUTPUT,40000) OUTLIN
OUTCT = OUTCT + 1
C --- ANYTHING TO CLOSE THE OUTPUT FILE:
ENDFILE OUTPUT
90 CONTINUE
RETURN
END
C
C
SUBROUTINE GETBYT(BYTE,INPUT,INCT,INBYTE,INPT,CONTRL,ZFOUND)
C
C GET ONE BYTE FROM INPUT; UPDATE COUNT OF SECTORS (INCT),
C COUNT OF INPUT BYTES(INBYTE) (EVEN IF THAT'S NEARLY REDUNDANT...)
C AND POINTER INTO INPUT BUFFER (INPT).
C ZFOUND IS TRUE IFF BYTE WAS FOUND.
C REPORT PROGRESS ON UNIT CONTRL.
C
IMPLICIT INTEGER*4 (A-Z)
LOGICAL*4 ZFOUND
C --- UFT IS NEEDED FOR MODCOMP BINARY READ:
DIMENSION SECTOR(64),UFT(5)
C THESE VARIABLES ARE FOR MODCOMP USE ONLY:
DATA OPTION/36864/, EOFBIT/2097152/
C --- SECLEN IS NUMBER OF BYTES IN A TYPICAL, FIXED-LENGTH BINARY RECORD:
DATA SECLEN/256/
C
BYTE = 0
IF (.NOT.ZFOUND) GOTO 95
C --- CHECK IF FIRST CALL:
IF (INCT.NE.0) GOTO 10
C --- YES; ANYTHING TO INITIALIZE INPUT FILE FOR READING GOES HERE;
C READING MUST BE UNDISTURBED BY ANY CONTROL CHARACTERS:
C --- INITIALIZE UFT FOR READING (MODCOMP; REPLACE WITH WHATEVER YOU
C NEED):
C
CALL BLDUFT(UFT,0,ICAN4(INPUT),OPTION)
C
GOTO 12
10 CONTINUE
C --- IS SOMETHING LEFT IN THE BUFFER?
IF (INPT.LT.SECLEN) GOTO 20
C --- NO; GET NEXT SECTOR:
12 INCT = INCT + 1
C --- DO A BINARY READ OF SECLEN BYTES = ONE RECORD:
C (AGAIN, REPLACE WITH WHATEVER YOU NEED, MAYBE A PLAIN READ WITH
C FORMAT (64A4) WILL DO FOR YOU. REMEMBER TO CHECK FOR END OF FILE.)
C
CALL READ4(UFT,SECTOR,SECLEN)
C
C --- END OF FILE??
IF (IAND(UFT(1),EOFBIT).NE.0) GOTO 90
C --- NO; NEXT SECTOR FOUND:
C --- REPORT PROGRESS ON CONTROL UNIT FROM TIME TO TIME:
IF (MOD(INCT,64).EQ.0) WRITE (CONTRL,17000) INCT
17000 FORMAT ('+Record',I9)
INPT = 0
20 CONTINUE
C --- GET NEXT BYTE FROM BUFFER:
INPT = INPT + 1
INBYTE = INBYTE + 1
CALL EXTRCH(BYTE,SECTOR,INPT)
GOTO 95
90 CONTINUE
ZFOUND = .FALSE.
95 CONTINUE
RETURN
END
C
C
SUBROUTINE EXTRCH(C,BUFFER,POS)
C
C GET POS-TH BYTE FROM BUFFER, RETURN IT RIGHT-JUSTIFIED WITHIN C:
C BUFFER IS REGARDED AS TIGHTLY PACKED 32-BIT-QUANTITIES-ARRAY
C
IMPLICIT INTEGER*4 (A-Z)
DIMENSION BUFFER(1)
C THESE ARE THE RIGHT-MOST 8 BITS:
DATA RBYTE/255/
C
I = (POS+3) / 4
K = POS - 4*(I-1)
C = BUFFER(I)
C --- NOW SHIFT; BUT FOR THE BENEFIT OF SOME FAULTY COMPILERS,
C DONT'T IF SHIFT COUNT IS 0:
IF (K.NE.4) C = ISHFT(C,8*K-32)
C = IAND(C,RBYTE)
RETURN
END
C
C
SUBROUTINE INSRCH(C,BUFFER,POS)
C
C INSERT RIGHT-MOST BYTE OF C INTO POS-TH BYTE OF BUFFER.
C ASSUME C IS 0 IN 3 FIRST BYTES AND THERE ARE NO SIGNIFICANT BYTES
C AFTER POS IN BUFFER
C BUFFER IS REGARDED AS TIGHTLY PACKED 32-BIT-QUANTITIES-ARRAY
C
IMPLICIT INTEGER*4 (A-Z)
DIMENSION BUFFER(1)
C THIS IS A VARIABLE WITH EACH AND EVERY BIT SET; IF YOUR MACHINE
C DOESN'T USE TWO'S COMPLEMENT, YOU GOT TO FIGURE OUT HOW TO DO IT:
DATA FULLBT/-1/
C
I = (POS+3)/4
K = POS - 4*(I-1)
CA = C
C --- NOW SHIFT; BUT FOR THE BENEFIT OF SOME FORTRAN COMPILERS,
C DON'T IF SHIFT COUNT IS ZERO:
IF (K.NE.4) CA = ISHFT(CA,32-8*K)
MASK = ISHFT(FULLBT,40-8*K)
BUFFER(I) = IOR(IAND(BUFFER(I),MASK),CA)
RETURN
END