home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
old
/
ckermit5a190
/
ckvhex.mar
< prev
next >
Wrap
Text File
|
2020-01-01
|
19KB
|
630 lines
.TITLE HEXIFY
.SBTTL Stuart Hecht and Eric McQueen
.LIBRARY /SYS$LIBRARY:STARLET/
.LIBRARY /SYS$LIBRARY:LIB/
.IDENT /1.2/
;
; Define ALPHA if R22 is a register and not a symbol
;
.NTYPE ...IS_IT_ALPHA,R22 ;Get the type of R22
...IS_IT_ALPHA = <...IS_IT_ALPHA@-4&^XF>-5
.IIF EQ,...IS_IT_ALPHA, ALPHA=1
;1.2
;Updated July 2, 1993 by Hunter Goatley, Western Kentucky University
;<goathunter@WKUVX1.BITNET>
;Ported to run under OpenVMS AXP. Changed JSBs and BRWs to BSBWs and BRWs.
;Could use a lot more cleanup, but I don't have the time....
;++
;This will take a task file and turn it into hexidecimal strings
;--
;++
;Modified by Jeff Guerber, STX, (xrjrg@lepvax.gsfc.nasa.gov), June 4, 1991,
;to save the file organization (fab$b_org). Marked by "JRG". 1.1.03
;It might be better to store the entire FAB.
;--
.EXTRN LIB$GET_INPUT
.EXTRN LIB$PUT_OUTPUT
.EXTRN DSC$K_DTYPE_T
.EXTRN DSC$K_CLASS_S
.EXTRN SS$_NORMAL
.EXTRN RMS$_EOF
.MCALL $FAB ; RMS calls
.MCALL $RAB
.MCALL $CLOSE
.MCALL $CONNECT
.MCALL $CREATE
.MCALL $DISCONNECT
.MCALL $READ
.MCALL $OPEN
.MCALL $PUT
.MCALL $RAB_STORE
.MCALL $FAB_STORE
.SBTTL Definitions of symbols
DWRLUN =1 ; Disk read LUN
DWWLUN =5 ; Disk write LUN
KNORMAL =0 ; No error
EOF =-1 ; End of file error code
LEFTBYTE=^O377*^O400 ; All one in left byte
HEXOFFSET=7 ; Offset to get to 'A from '9+1
CR =13. ; Carriage return
LF =10. ; Line feed
; Packet types currently created
PKDATA =0 ; Data packet code
PKRFM =255. ; Record format
PKRAT =254. ; Record attributes
PKMRS =253. ; Maximum record size
PKALQ =252. ; File length(blocks)
PKFILNM =251. ; File name
PKEOF =250. ; End of file
PKORG =249. ; File organization (seq, idx, etc)
.SBTTL Data
.PSECT $PLIT$,LONG
M$FILN: .BYTE CR,LF,LF
.ASCII 'Input file name: '
L$FILN =.-M$FILN
.ALIGN LONG
M$OFLN: .BYTE CR,LF,LF
.ASCII 'Output file name (or return for the default): '
L$OFLN =.-M$OFLN
.ALIGN LONG
M$NEXF: .BYTE CR,LF,LF
.ASCII 'Press return to finish or type the name of another file'
.BYTE CR,LF
.ASCII 'to append to the HEX file: '
L$NEXF =.-M$NEXF
.ALIGN LONG
M$RMS: .BYTE CR,LF,LF
.ASCII 'RMS ERROR'
L$RMS =.-M$RMS
.EVEN
.SBTTL RMS Data
.ALIGN LONG
DEFALT: .ASCIZ 'SYS$DISK:' ; System default.
DEFALN =.-DEFALT ; Size of the default device.
.EVEN
.SBTTL Storage locations
.PSECT $OWN$,LONG
.ALIGN LONG
MSGDSC: .BLKW 1 ; Data block for terminal output
.BYTE DSC$K_DTYPE_T
.BYTE DSC$K_CLASS_S
ADDR: .ADDRESS ADDR
LNGADR: .BLKL 1
INP_STR_D: ; Key string desciptor
.BLKL 1
INP_BUF: .ADDRESS ADDR
INP_STR_LEN: ; Key string length
.BLKL 1
BUCOUNT: .BLKL 1 ; Number of character available in the
; buffer (returned from RMS)
RDCOUNT: .BLKL 1 ; Number of characters read from buffer
WTCOUNT: .BLKL 1 ; Number of characters written
CHCOUNT: .BLKL 1 ; Number of characters written to buff.
NULCOUNT: .BLKL 1 ; Number of nulls not yet written
CHKSUM: .BLKL 1 ; Checksum for the line
ADDRESS: .BLKL 1 ; Current address
INP.N: .BLKB 28. ; Space for input file name
INP.L =.-INP.N ; Length of input file name
OUT.N: .BLKB 28. ; Space for output file name
OUT.L =.-OUT.N ; Length of input file name
RDBUF: .BLKB 512. ; Disk read buffer
WTBUF: .BLKB 512. ; Disk write buffer
.EVEN
.SBTTL RMS Data structures
.ALIGN LONG
RDFAB:: $FAB DNA=DEFALT,DNS=DEFALN,FNA=INP.N,FNS=INP.L,-
LCH=DWRLUN,FAC=<GET,BIO>,SHR=GET
.ALIGN LONG
RDRAB:: $RAB FAB=RDFAB,RAC=SEQ
; Beginning of RAB block.
.ALIGN LONG
WTFAB:: $FAB DNA=DEFALT,DNS=DEFALN,FNA=OUT.N,FNS=OUT.L,-
LCH=DWWLUN,FAC=PUT,SHR=NIL,ORG=SEQ,RAT=CR,RFM=VAR
.ALIGN LONG
WTRAB:: $RAB FAB=WTFAB,RAC=SEQ
; Beginning of RAB block.
.SBTTL Main line code
.PSECT $CODE$,LONG,EXE
.ALIGN LONG
.ENTRY HEXIFY,^M<>
NOINP:
MOVAB M$FILN,R11 ; Get the input prompt address
MOVL #L$FILN,R12
MOVAB INP.N,R10 ; Get address of input and length
MOVL #INP.L,R1 ;
BSBW READ ; Read the input file name
TSTL R0 ; See if we got anything
BEQL NOINP ; If no input then try again
MOVL R0,R5 ; Save length
MOVAB M$OFLN,R11 ; Get the address of the prompt
MOVL #L$OFLN,R12
MOVAB OUT.N,R10 ; Get address of output file name
MOVL #OUT.L,R1 ; and length
BSBW READ ; Read the output file name
MOVL R0,R3 ; Save length
TSTL R3 ; See if we got any input
BNEQ GOTFIL ; Yes so branch
; Here so use the default output file name
MOVL R5,R0 ; Get the input file length back
MOVAB INP.N,R2 ; Get input address
MOVAB OUT.N,R3 ; Point at buffer
CLRL R1 ; Clear the character count
10$: CMPB (R2),#^A/./ ; Check for an extension
BEQL 20$ ; If an extension then ignore rest
; of line
MOVB (R2)+,(R3)+ ; Move into the output file name
INCW R1 ; Increment counter
SOBGTR R0,10$ ; Branch until done
20$: MOVB #^A/./,(R3)+ ; Write the extension for output file
MOVB #^A/H/,(R3)+ ;
MOVB #^A/E/,(R3)+ ;
MOVB #^A/X/,(R3)+ ;
ADDW3 #4,R1,R3 ; Get final character count
;++
;Open files
;--
GOTFIL:
;Create output file
MOVAL WTFAB,R1 ; Put address of FAB into R1.
$FAB_STORE FAB=R1,FNS=R3 ; Tell RMS file name length
$CREATE #WTFAB ; Create the file
BSBW RMSERR ; Check for file error
MOVAL WTRAB,R1 ; Put address of RAB into R1.
$RAB_STORE RAB=R1,UBF=WTBUF,RBF=WTBUF,USZ=#512.,RSZ=#512.
; Put address of user buffer in RAB.
$CONNECT #WTRAB ; Connect to record.
BSBW RMSERR ; Check for file error
;Open input file
AGAINSAM:
MOVAL RDFAB,R1 ; Put address of FAB into R1.
$FAB_STORE FAB=R1,FNS=R5 ; Tell RMS file name length
$OPEN #RDFAB ; Open the file
BSBW RMSERR ; Check for file error
MOVAL RDRAB,R1 ; Put address of RAB into R1.
$RAB_STORE RAB=R1,UBF=RDBUF,RBF=RDBUF,USZ=#512.,RSZ=#512.
$CONNECT #RDRAB ; Connect to record.
BSBW RMSERR ; Check for file error
;++
;Do the actual work
;--
MOVZWL #512.,RDCOUNT ; Initialize buffer pointers
MOVZWL #512.,BUCOUNT ;
CLRL WTCOUNT ;
CLRL ADDRESS ; Initialize the address
CLRL NULCOUNT ; Initialize the number of nulls
MOVAL RDFAB,R5 ; Get the FAB address
;Get the Record format (FIX, VAR, ...)
MOVZBL #PKRFM,R10 ; Set packet type to record format
BSBW HEADER ; Output the header
MOVZBL FAB$B_RFM(R5),R10
BSBW CVTH ; Put the record format code into buff
INCL CHCOUNT ; Increment counter
BSBW PUTLIN ; Write the line out
;Get the record type (CR, ...)
MOVZBL #PKRAT,R10 ; Set packet type to record type
BSBW HEADER ; Output the header
MOVZBL FAB$B_RAT(R5),R10
BSBW CVTH ; Put the record type into buffer
INCL CHCOUNT ; Increment counter
BSBW PUTLIN ; Write the line out
;Get the file organization (SEQ, IDX, etc). JRG.
MOVZBL #PKORG,R10 ; Set packet type to organization
BSBW HEADER ; output the header
MOVZBL FAB$B_ORG(R5),R10
BSBW CVTH ; Put organization code into buffer
INCL CHCOUNT ; Increment counter
BSBW PUTLIN ; Write the line out
;Get the maximum record size (512. for tasks)
MOVZBL #PKMRS,R10 ; Set packet type to max record size
BSBW HEADER ; Output the header
MOVZWL FAB$W_MRS(R5),R10
PUSHL R10 ; Save for low order
EXTZV #8.,#8.,R10,R10 ; Get high order byte
BSBW CVTH ; Put the record size into buffer
INCL CHCOUNT ; Increment counter
POPL R10 ; Get size back
BSBW CVTH ; Put the record size into buffer
INCL CHCOUNT ; Increment counter
BSBW PUTLIN ; Write the line out
;Get the file length (in blocks)
MOVZWL #PKALQ,R10 ; Set packet type to file length
BSBW HEADER ; Output the header
MOVL FAB$L_ALQ(R5),R10
PUSHL R10 ; Save for low order
EXTZV #8.,#8.,R10,R10 ; Get high order byte
BSBW CVTH ; Put the allocation into buffer
INCL CHCOUNT ; Increment counter
POPL R10 ; Get allocation back
BSBW CVTH ; Put the low order into the buffer
INCL CHCOUNT ; Increment counter
BSBW PUTLIN ; Write the line out
;Get the file name
MOVZBL #PKFILNM,R10 ; Set packet type to file name
BSBW HEADER ; Output the header
MOVZBL FAB$B_FNS(R5),R4
MOVAB INP.N,R3 ; Get the input file name address
10$: MOVZBL (R3)+,R10 ; Get the next character
BSBW CVTH ; Buffer the next character of the name
INCL CHCOUNT ; Increment counter
SOBGTR R4,10$ ; Repeat until all done
BSBW PUTLIN ; Write the line out
;++
; Start moving real data
;--
NEXLIN:
BSBW GET ; Get a character from the buffer
CMPL R10,#EOF ; Check for end of file
BEQL FINISH ; If at end the finish up
TSTL R10 ; Check for null character
BNEQ DOLIN ; Not null so just do regular stuff
INCL ADDRESS ; Point to next location
BRB NEXLIN ; save space and try again
DOLIN: PUSHL R10 ; Save the character we have
MOVZWL #PKDATA,R10 ; Set packet type to plain old data
BSBW HEADER ; Put the standard header into buffer
POPL R10 ; Get the original character back
LINAGA: BSBW CVTHEX ; Convert the character to hex codes
INCL ADDRESS ; Point to next location
INCL CHCOUNT ; Increment the character count
CMPL CHCOUNT,#^O36 ; Check to see if we should finish
BNEQ LINMOR ; this line
BSBW PUTLIN ; Put the whole line to disk
BRW NEXLIN ; Go do the next line
LINMOR: BSBW GET ; Get the next character
CMPL R10,#EOF ; Is it an end of file?
BNEQ LINAGA ; No, then just handle normally
; BSBW PUTLIN ; Yes, write the current line
DECL ADDRESS ; Reset address to correct value
BRW FIN1 ; Finish up
.SBTTL Finish up
;++
;Finish up
;--
FINISH:
MOVZBL #PKDATA,R10 ; Set packet type to plain old data
BSBW HEADER ; Insert the header so the extra
; nulls are seen
FIN1: TSTL NULCOUNT ; See if no nulls left
BEQL FIN ; If none then branch
CLRL R10 ; Get a null
DECL NULCOUNT ; Decrement the counter
BSBW CVTH ; Convert to HEX (w/o null compression)
FIN: BSBW PUTLIN ; Put the current buffer to disk
; Write out the end of task file line
CLRL CHCOUNT ; Clear character count
MOVZBL #PKEOF,R10 ; Get end of task file packet type
BSBW HEADER ; Make the header
BSBW PUTLIN ; Write the line
; Close the input (task) file
MOVAL RDFAB,R1 ; Get the FAB for input file
$CLOSE R1 ; Close input file
BSBW RMSERR ; Check for file error
; See about another file to append
MOVAB M$NEXF,R11 ; See if another file should be
MOVL #L$NEXF,R12 ; appended to the HEX file
MOVAB INP.N,R10 ;
MOVL #INP.L,R1 ; Get address of input and length
BSBW READ ; Read the input file name
TSTL R0 ; See if we got anything
BEQL LEAVE ; If no input then leave
MOVL R0,R5 ; Put the length in R5 for the open
BRW AGAINSAM ; Repeat process for this file
; Write out end of hex file line
LEAVE: CLRL CHKSUM ; Clear the checksum for this line
CLRL CHCOUNT ; Clear character count
MOVZBL #^A/</,R10 ; Get the start character
BSBW BUFFER ; Put it into the buffer
MOVZBL #12.,R5 ; Get the number of nulls needed
FINREP: MOVZBL #^A/0/,R10 ; Set the character to 'null'
BSBW BUFFER ; Put it into the buffer
SOBGTR R5,FINREP ; Repeat if not done
BSBW PUTLIN ; Write the buffer to disk
; Close the HEX file
MOVAL WTFAB,R1 ; Get FAB for output file
$CLOSE R1 ; Close output file
BSBW RMSERR ; Check for file error
END:
MOVL #SS$_NORMAL,R0 ; Set up successful completion
RET ; Exit program
.SBTTL Put a data line
;++
;Finish a line up by inserting the length and the checksum and doing a PUT
;--
PUTLIN:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10>,OUTPUT=<R10>
MOVL CHCOUNT,R10 ; Get the actual character count
SUBL2 NULCOUNT,R10 ; Don't include the nulls since we
; won't write them
CLRL NULCOUNT ; Clear the null count since the
; address will serve to insert nulls
PUSHL WTCOUNT ; Save it on the stack
MOVZBL #1,WTCOUNT ; Move a one into the char count to get
BSBW CVTH ; to the length and then put length in
POPL WTCOUNT ; Restore the correct count
MNEGL CHKSUM,R10 ; Negate it
BSBW CVTH ; Put the negative checksum into buffer
BSBW PUT ; Put the line to disk
RSB ; Return to sender
.SBTTL Create the header for the data line
;++
;This routine will put the starting stuff into the buffer
;R10 contains the record type
;--
HEADER:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10>,OUTPUT=<R10>
CLRL CHKSUM ; Clear the checksum for this line
CLRL CHCOUNT ; Clear character count
PUSHL R10 ; Save the record type
MOVZBL #^A/</,R10 ; Move a less-than into first char
BSBW BUFFER ; position of the buffer
CLRL R10 ; Move a fake length into the buffer
BSBW CVTH ;
MOVZBL ADDRESS+3,R10 ; Get the highest order byte of the
BSBW CVTH ; address and put into the buffer
MOVZBL ADDRESS+2,R10 ; Get the 2nd highest order byte of the
BSBW CVTH ; address and put into the buffer
MOVZBL ADDRESS+1,R10 ; Get the 2nd lowest order byte of the
BSBW CVTH ; address and put into the buffer
MOVZBL ADDRESS,R10 ; Get the lowest order byte of the
BSBW CVTH ; address and buffer it
POPL R10 ; Get the line record type
BSBW CVTH ; and buffer the code
RSB ; Return to sender
.SBTTL Output and input to/from terminal
;++
; Write data to terminal.
; R10 Address of data to output
; R1 Length of data
;--
WRITE:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R1,R10>
MOVW R1,MSGDSC ; Store the length in the descript blk
MOVL R10,ADDR ; Store the address of the ASCII
PUSHAQ MSGDSC ; Push the descriptor block address
CALLS #1,G^LIB$PUT_OUTPUT ; Do the output
RSB ; Return to sender
;++
; Read from the terminal
; R10 Address of buffer
; R1 Number of characters to read
; R11 Input prompt address
; R12 Length of prompt
;
;Returned:
; R0 Number of characters read
;--
READ:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10,R1,R11,R12>
MOVL R1,INP_STR_D ; Store the buffer length in desc block
MOVL R10,INP_BUF ; Store the buffer address in desc blk
MOVL R11,ADDR ; Store prompt address in desc block
MOVW R12,MSGDSC ; Store length in desctriptor block
PUSHAB INP_STR_LEN ; Address for string length
PUSHAQ MSGDSC ; Push address of prompt descriptor blk
PUSHAB INP_STR_D ; String buffer descriptor
CALLS #3,G^LIB$GET_INPUT ; Get input string value
MOVL INP_STR_LEN,R0 ; Get actual input length back
RSB ; Return to sender
.SBTTL RMS error routine
;++
;Check for RMS error
;--
RMSERR:
.IIF DF,ALPHA, .JSB_ENTRY PRESERVE=<R10>
BLBC R0,10$ ; If error, go check it out
MOVL #KNORMAL,R0 ; Set up a successful return code.
RSB ; Return to caller
; Here if there is an error
10$: CMPL #RMS$_EOF,R0 ; Check for EOF
BNEQ 20$ ; If not then branch
MOVL #EOF,R0 ; Tell sender we have end of file
RSB ; Return
; Here if there is an RMS error we don't know how to handle
20$: PUSHL R0 ; Save the error code
MOVAB M$RMS,R10 ; Get the address and length of the
MOVL #L$RMS,R1 ; message to output
BSBW WRITE ; Output it
POPL R0 ; Get the error code back
$EXIT_S CODE=R0 ; Exit the program
.IIF DF,ALPHA, RSB ; RSB to keep compiler from warning
.SBTTL Get a character from the file
;++
;Get a character from the input file.
;
; Returned:
; R10 Contains the character if not at end of file
; Contains #EOF if at end of file
;--
GET:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10>,OUTPUT=<R10>
MOVL RDCOUNT,R10 ; Get the offset into the buffer
CMPL R10,BUCOUNT ; Check to see if we are past the end
BNEQ 20$ ; If not then branch
MOVAL RDRAB,R1 ; Get the RAB address
$RAB_STORE RAB=R1,UBF=RDBUF,USZ=#512.
$READ R1 ; Get the next buffer of data.
BSBW RMSERR ; Check for file error
CMPL R0,#EOF ; Check for end of file error
BNEQ 10$ ; If not then branch
MOVL R0,R10 ; Move the status to the correct spot
RSB ; Return with error code
10$:
MOVZWL RAB$W_RSZ+RDRAB,R10
MOVL R10,BUCOUNT ; Save the record size
CLRL R10 ; Clear the pointer
CLRL RDCOUNT ; . . .
20$: MOVZBL RDBUF(R10),R10 ; Get the next character
INCL RDCOUNT ; Increment the offset into the buffer
RSB ; Return to sender
.SBTTL Buffer a character of the data line
;++
; Buffer the character in R10
;--
BUFFER:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10>,OUTPUT=<R10>
PUSHL R10 ; Save the character on the stack
MOVL WTCOUNT,R10 ; Get the offset into the buffer
CMPL #512.,R10 ; Get too big?
BGTR BUFOK
NOP
BUFOK: MOVB (SP),WTBUF(R10) ; Move the character to the buffer
TSTL (SP)+ ; Remove the junk
INCL WTCOUNT ; Increment the pointer
BUFRTS: RSB ; Return to sender
.SBTTL Put a record to the file
;++
;Write the record
;--
PUT:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10>,OUTPUT=<R10>
MOVL WTCOUNT,R10 ; Get the count
MOVAL WTRAB,R1 ; Get the RAB address
$RAB_STORE RAB=R1,RSZ=R10
$PUT R1 ; Output the record
BSBW RMSERR ; Check for file error
CLRL WTCOUNT ; Clear the counter for next record
RSB ; Return
.SBTTL Convert to Hexadecimal ASCII digits
;++
; Convert a word to 2 ASCII hexadecimal digits
;--
CVTHEX:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10>,OUTPUT=<R10>,PRESERVE=<R4,R5>
TSTL R10 ; See if this is a null
.IF DEFINED ALPHA
BEQL 10$ ; Branch if so
BSBW CVTH ; Branch to other subroutine, but use
RSB ; ... BSBW to keep compiler happy
10$:
.IFF
BNEQ CVTH ; If not then just branch
.ENDC
INCL NULCOUNT ; A null so just increment the count
RSB ; for later and leave
; Convert a word to 2 ASCII hexadecimal digits without null compression
CVTH:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10>,OUTPUT=<R10>,PRESERVE=<R3,R4,R5>
PUSHL R10 ; Save the character on the stack
10$: TSTL NULCOUNT ; Check to see if there are nulls
BEQL 20$ ; If not then just branch
CLRL R10 ; Put a null in R10
BSBW CVT1 ; Put the null in the buffer
DECL NULCOUNT ; Decrement null counter
BRB 10$ ; Repeat
20$: POPL R10 ; Get the original value back
.IF DEFINED ALPHA ;* For AXP, don't just drop through.
BSBW CVT1 ;... Instead, use a BSBW/RSB to keep
RSB ;... the compiler from warning
.ENDC ;* VAX just drops on through
CVT1:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10>,OUTPUT=<R10>
ADDL2 R10,CHKSUM ; Add the value to the checksum
MOVL R10,R1 ; Save the value
EXTZV #4,#4,R10,R10 ; Get high order digit
BSBW HEX ; in place and convert to Hex
BSBW BUFFER ; Buffer the Hex character
EXTZV #0,#4,R1,R10 ; Get right digit
BSBW HEX ; Convert to Hex
BSBW BUFFER ; Buffer the Hex character
RSB ; Return to sender
HEX:
.IIF DF,ALPHA, .JSB_ENTRY INPUT=<R10>,OUTPUT=<R10>
MOVL R10,R2 ; Move the base to R2
CMPL R2,#9. ; Check to see if above '9
BLEQ 10$ ; If not then branch
ADDL2 #HEXOFFSET,R10 ; Add offset to alphabet
10$: ADDL2 #48.,R10 ; Make ASCII
RSB ; Return to sender
.SBTTL End of Hexify
.END HEXIFY