home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
decpro300.tar.gz
/
decpro300.tar
/
prohex.mac
< prev
next >
Wrap
Text File
|
1988-08-16
|
17KB
|
565 lines
.TITLE HEXIFY
.SBTTL Stuart Hecht
.LIBRARY /LB:[1,5]RMSMAC/
.ENABLE LC
.NLIST BEX
.IDENT /1.0.00/
;++
;This will take a task file and turn it into hexidecimal strings
;--
.MCALL QIOW$S,QIOW$,ALUN$S,EXIT$S
.MCALL FAB$B ; RMS calls
.MCALL RAB$B
.MCALL $CLOSE
.MCALL $CONNECT
.MCALL $CREATE
.MCALL $DISCONNECT
.MCALL $READ
.MCALL $OPEN
.MCALL $FETCH
.MCALL $PUT
.MCALL $STORE
.MCALL $SET
.MCALL ORG$
.MCALL POOL$B
.SBTTL Definitions of symbols
TERLUN =7 ; Terminal LUN
TTEFN =1 ; Terminal Event Flag
DWRLUN =1 ; Disk read LUN
DWWLUN =5 ; Disk write LUN
TRUE =1 ; True
FALSE =0 ; False
KNORMAL =0 ; No error
RMS11 =1 ; RMS error
EOF =-1 ; End of file error code
LEFTBYTE=377*400 ; All one in left byte
HEXOFFSET=7 ; Offset to get to 'A from '9+1
; 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
;
.SBTTL RMS Initialization
POOL$B ; Allocate static pool for RMS
P$RAB 5 ; For internal RABs
P$BDB 5 ; For buffer descriptor blocks
P$FAB 4 ; For internal FABs
P$BUF 2048. ; Buffer space
POOL$E ; End of pool declarations
ORG$ SEQ ; $Open a sequential file
.SBTTL Data
.PSECT $PLIT$,RO,D
M$FILN: .BYTE CR,LF,LF
.ASCII 'Input file name: '
L$FILN =.-M$FILN
M$OFLN: .BYTE CR,LF,LF
.ASCII 'Output file name (or return for the default): '
L$OFLN =.-M$OFLNM
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
M$RMS: .BYTE CR,LF,LF
.ASCII 'RMS ERROR'
L$RMS =.-M$RMS
.EVEN
.SBTTL RMS 11 Data
DEFALT: .ASCIZ 'SY:' ; System default.
DEFALN =.-DEFALT ; Size of the default device.
.EVEN
.SBTTL Storage locations
.PSECT $OWN$
IOSTAT: .BLKW 1 ; QIO status
STAT1: .BLKW 1 ; Second word of status
BUCOUNT: .BLKW 1 ; Number of character available in the
; buffer (returned from RMS)
RDCOUNT: .BLKW 1 ; Number of characters read from buffer
WTCOUNT: .BLKW 1 ; Number of characters written
CHCOUNT: .BLKW 1 ; Number of characters written to buff.
NULCOUNT: .BLKW 1 ; Number of nulls not yet written
CHKSUM: .BLKW 1 ; Checksum for the line
ADDRESS: .BLKW 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 11 Data structures
RDFAB:: FAB$B
F$DNA DEFALT ; Address of default device.
F$DNS DEFALN ; Default length field.
F$FNA INP.N ; Address of file name
F$FNS INP.L ; Length of file name
F$LCH DWRLUN ; Logical channel to use
FAB$E
.EVEN
RDRAB:: RAB$B ; Beginning of RAB block.
R$FAB RDFAB ; Chain to FAB block.
R$RAC RB$SEQ ; Set the sequential access flag.
RAB$E ; End RAB block.
.EVEN
WTFAB:: FAB$B
F$DNA DEFALT ; Address of default device.
F$DNS DEFALN ; Default length field.
F$FNA OUT.N ; Address of file name
F$FNS OUT.L ; Length of file name
F$LCH DWWLUN ; Logical channel to use
FAB$E
.EVEN
WTRAB:: RAB$B ; Beginning of RAB block.
R$FAB WTFAB ; Chain to FAB block.
R$RAC RB$SEQ ; Set the sequential access flag.
RAB$E ; End RAB block.
.EVEN
.SBTTL Main line code
.PSECT $CODE$,RO,I
HEXIFY::
ALUN$S #TERLUN,#"TI,#0 ; Assign terminal LUN
NOINP: MOV #M$FILN,R0 ; Get the address and length of the
MOV #L$FILN,R1 ; message to output
JSR PC,WRITE ; Output it
MOV #INP.N,R0 ; Get address of input and length
MOV #INP.L,R1 ;
JSR PC,READ ; Read the input file name
TST R0 ; See if we got anything
BEQ NOINP ; If no input then try again
MOV R0,R5 ; Save length
MOV #M$OFLN,R0 ; Get the address and length of the
MOV #L$OFLN,R1 ; message to output
JSR PC,WRITE ; Output it
MOV #OUT.N,R0 ; Get address of output file name
MOV #OUT.L,R1 ; and length
JSR PC,READ ; Read the output file name
MOV R0,R3 ; Save length
TST R3 ; See if we got any input
BNE GOTFIL ; Yes so branch
; Here so use the default output file name
MOV R5,R0 ; Get the input file length back
MOV #INP.N,R2 ; Get input address
MOV #OUT.N,R3 ; Point at buffer
2$: CMPB (R2),#'. ; Check for an extension
BEQ 10$ ; If an extension then ignore rest
; of line
MOVB (R2)+,(R3)+ ; Move into the output file name
SOB R0,2$ ; Branch until done
10$: MOVB #'.,(R3)+ ; Write the extension for output file
MOVB #'H,(R3)+ ;
MOVB #'E,(R3)+ ;
MOVB #'X,(R3)+ ;
SUB #OUT.N,R3 ; Make final count
;++
;Open files
;--
GOTFIL:
;Create output file
MOV #WTFAB,R1 ; Put address of FAB into R1.
$SET #FB$CR,RAT,R1 ; Set the record handling mask.
$STORE R3,FNS,R1 ; Tell RMS file name length
$CREATE #WTFAB ; Create the file
JSR PC,RMSERR ; Check for file error
MOV #WTRAB,R1 ; Put address of RAB into R1.
$STORE #WTBUF,UBF,R1 ; Put address of user buffer in RAB.
$STORE #WTBUF,RBF,R1 ; Put record buffer address in RAB
$STORE #512.,USZ,R1 ; Put size of user buffer into RAB.
$STORE #512.,RSZ,R1 ; Put record buffer size in RAB
$CONNECT #WTRAB ; Connect to record.
JSR PC,RMSERR ; Check for file error
;Open input file
AGAINSAM:
MOV #RDFAB,R1 ; Put address of FAB into R1.
$SET #FB$REA,FAC,R1 ; Set the block read in FAB.
$STORE R5,FNS,R1 ; Tell RMS file name length
$OPEN #RDFAB ; Open the file
JSR PC,RMSERR ; Check for file error
MOV #RDRAB,R1 ; Put address of RAB into R1.
$STORE #RDBUF,UBF,R1 ; Put address of user buffer in RAB.
$STORE #RDBUF,RBF,R1 ; Put record buffer address in RAB
$STORE #512.,USZ,R1 ; Put size of user buffer into RAB.
$STORE #512.,RSZ,R1 ; Put record buffer size in RAB
$CONNECT #RDRAB ; Connect to record.
JSR PC,RMSERR ; Check for file error
;++
;Do the actual work
;--
MOV #512.,RDCOUNT ; Initialize buffer pointers
MOV #512.,BUCOUNT ;
CLR WTCOUNT ;
CLR ADDRESS ; Initialize the address
CLR NULCOUNT ; Initialize the number of nulls
MOV #RDFAB,R5 ; Get the FAB address
;Get the Record format (FIX, VAR, ...)
MOV #PKRFM,R0 ; Set packet type to record format
JSR PC,HEADER ; Output the header
$FETCH R0,RFM,R5 ; Get the record format
JSR PC,CVTH ; Put the record format code into buff
INC CHCOUNT ; Increment counter
JSR PC,PUTLIN ; Write the line out
;Get the record type (CR, ...)
MOV #PKRAT,R0 ; Set packet type to record type
JSR PC,HEADER ; Output the header
$FETCH R0,RAT,R5 ; Get the record type
JSR PC,CVTH ; Put the record type into buffer
INC CHCOUNT ; Increment counter
JSR PC,PUTLIN ; Write the line out
;Get the maximum record size (512. for tasks)
MOV #PKMRS,R0 ; Set packet type to max record size
JSR PC,HEADER ; Output the header
$FETCH R0,MRS,R5 ; Get the maximum record size
MOV R0,-(SP) ; Save for low order
SWAB R0 ; Get high order byte
JSR PC,CVTH ; Put the record size into buffer
INC CHCOUNT ; Increment counter
MOV (SP)+,R0 ; Get size back
JSR PC,CVTH ; Put the record size into buffer
INC CHCOUNT ; Increment counter
JSR PC,PUTLIN ; Write the line out
;Get the file length (in blocks)
MOV #PKALQ,R0 ; Set packet type to file length
JSR PC,HEADER ; Output the header
$FETCH R0,ALQ,R5 ; Get the allocation
MOV R0,-(SP) ; Save for low order
SWAB R0 ; Get high order byte
JSR PC,CVTH ; Put the allocation into buffer
INC CHCOUNT ; Increment counter
MOV (SP)+,R0 ; Get allocation back
JSR PC,CVTH ; Put the low order into the buffer
INC CHCOUNT ; Increment counter
JSR PC,PUTLIN ; Write the line out
;Get the file name
MOV #PKFILNM,R0 ; Set packet type to file name
JSR PC,HEADER ; Output the header
$FETCH R4,FNS,R5 ; Get the file name length
MOV #INP.N,R3 ; Get the input file name address
25$: MOVB (R3)+,R0 ; Get the next character
JSR PC,CVTH ; Buffer the next character of the name
INC CHCOUNT ; Increment counter
SOB R4,25$ ; Repeat until all done
JSR PC,PUTLIN ; Write the line out
;++
; Start moving real data
;--
NEXLIN:
JSR PC,GET ; Get a character from the buffer
CMP R0,#EOF ; Check for end of file
BEQ FINISH ; If at end the finish up
TST R0 ; Check for null character
BNE DOLIN ; Not null so just do regular stuff
INC ADDRESS ; Point to next location
BR NEXLIN ; save space and try again
DOLIN: MOV R0,-(SP) ; Save the character we have
MOV #PKDATA,R0 ; Set packet type to plain old data
JSR PC,HEADER ; Put the standard header into buffer
MOV (SP)+,R0 ; Get the original character back
LINAGA: JSR PC,CVTHEX ; Convert the character to hex codes
INC ADDRESS ; Point to next location
INC CHCOUNT ; Increment the character count
CMP CHCOUNT,#36 ; Check to see if we should finish
BNE LINMOR ; this line
JSR PC,PUTLIN ; Put the whole line to disk
BR NEXLIN ; Go do the next line
LINMOR: JSR PC,GET ; Get the next character
CMP R0,#EOF ; Is it an end of file?
BNE LINAGA ; No, then just handle normally
; JSR PC,PUTLIN ; Yes, write the current line
DEC ADDRESS ; Reset address to correct value
BR FIN1 ; Finish up
.SBTTL Finish up
;++
;Finish up
;--
FINISH:
MOV #PKDATA,R0 ; Set packet type to plain old data
JSR PC,HEADER ; Insert the header so the extra
; nulls are seen
FIN1: TST NULCOUNT ; See if no nulls left
BEQ FIN ; If none then branch
CLR R0 ; Get a null
DEC NULCOUNT ; Decrement the counter
JSR PC,CVTH ; Convert to HEX (w/o null compression)
FIN: JSR PC,PUTLIN ; Put the current buffer to disk
; Write out the end of task file line
CLR CHCOUNT ; Clear character count
MOV #PKEOF,R0 ; Get end of task file packet type
JSR PC,HEADER ; Make the header
JSR PC,PUTLIN ; Write the line
; Close the input (task) file
MOV #RDFAB,R1 ; Get the FAB for input file
$CLOSE R1 ; Close input file
JSR PC,RMSERR ; Check for file error
; See about another file to append
MOV #M$NEXF,R0 ; See if another file should be
MOV #L$NEXF,R1 ; appended to the HEX file
JSR PC,WRITE ;
MOV #INP.N,R0 ; Get address of input and length
MOV #INP.L,R1 ;
JSR PC,READ ; Read the input file name
TST R0 ; See if we got anything
BEQ LEAVE ; If no input then leave
MOV R0,R5 ; Put the length in R5 for the open
JMP AGAINSAM ; Repeat process for this file
; Write out end of hex file line
LEAVE: CLR CHKSUM ; Clear the checksum for this line
CLR CHCOUNT ; Clear character count
MOV #':,R0 ; Get the start character
JSR PC,BUFFER ; Put it into the buffer
MOV #8.,R5 ; Get the number of nulls needed
FINREP: MOV #'0,R0 ; Set the character to 'null'
JSR PC,BUFFER ; Put it into the buffer
SOB R5,FINREP ; Repeat if not done
JSR PC,PUTLIN ; Write the buffer to disk
; Close the HEX file
MOV #WTFAB,R1 ; Get FAB for output file
$CLOSE R1 ; Close output file
JSR PC,RMSERR ; Check for file error
END: EXIT$S
.SBTTL Put a data line
;++
;Finish a line up by inserting the length and the checksum and doing a PUT
;--
PUTLIN:
MOV CHCOUNT,R0 ; Get the actual character count
SUB NULCOUNT,R0 ; Don't include the nulls since we
; won't write them
CLR NULCOUNT ; Clear the null count since the
; address will serve to insert nulls
MOV WTCOUNT,-(SP) ; Save it on the stack
MOV #1,WTCOUNT ; Move a one into the char count to get
JSR PC,CVTH ; to the length and then put length in
MOV (SP)+,WTCOUNT ; Restore the correct count
MOV CHKSUM,R0 ; Get the checksum
NEG R0 ; Negate it
JSR PC,CVTH ; Put the negative checksum into buffer
JSR PC,PUT ; Put the line to disk
RTS PC ; Return to sender
.SBTTL Create the header for the data line
;++
;This routine will put the starting stuff into the buffer
;R0 contains the record type
;--
HEADER: CLR CHKSUM ; Clear the checksum for this line
CLR CHCOUNT ; Clear character count
MOV R0,-(SP) ; Save the record type
MOV #':,R0 ; Move a colon into first char position
JSR PC,BUFFER ; of the buffer
CLR R0 ; Move a fake length into the buffer
JSR PC,CVTH ;
MOVB ADDRESS+1,R0 ; Get the high order word of the
JSR PC,CVTH ; address and put into the buffer
MOVB ADDRESS,R0 ; Get low order word of address and
JSR PC,CVTH ; buffer it
MOV (SP)+,R0 ; Get the line record type
JSR PC,CVTH ; and buffer the code
RTS PC ; Return to sender
.SBTTL Output and input to/from terminal
;++
; Write data to terminal.
; R0 Address of data to output
; R1 Length of data
;--
WRITE:
QIOW$S #IO.WVB,#TERLUN,#TTEFN,,#IOSTAT,,<R0,R1>
RTS PC
;++
; Read from the terminal
; R0 Address of buffer
; R1 Number of characters to read
;
;Returned:
; R0 Number of characters read
;--
READ: QIOW$S #IO.RVB!TF.ESQ,#TERLUN,#TTEFN,,#IOSTAT,,<R0,R1>
MOV STAT1,R0 ; Get the number of character read
RTS PC
.SBTTL RMS error routine
;++
;Check for RMS error
;--
RMSERR: $FETCH R0,STS,R1 ; Get the status and put it in R0
TST R0 ; Test the status code for success.
BMI 60$ ; If negative then branch.
MOV #KNORMAL,R0 ; Set up a successful return code.
RTS PC ; Return to caller
; Here if there is an error
60$: CMP #ER$EOF,R0 ; Check for EOF
BNE 70$ ; If not then branch
MOV #EOF,R0 ; Tell sender we have end of file
RTS PC ; Return
; Here if there is an RMS error we don't know how to handle
70$: MOV #M$RMS,R0 ; Get the address and length of the
MOV #L$RMS,R1 ; message to output
JSR PC,WRITE ; Output it
EXIT$S ; Exit since we can't finish
.SBTTL Get a character from the file
;++
;Get a character from the input file.
;
; Returned:
; R0 Contains the character if not at end of file
; Contains #EOF if at end of file
;--
GET: MOV RDCOUNT,R0 ; Get the offset into the buffer
CMP R0,BUCOUNT ; Check to see if we are past the end
BNE 10$ ; If not then branch
MOV #RDRAB,R1 ; Get the RAB address
$READ R1 ; Get the next buffer of data.
JSR PC,RMSERR ; Check for file error
CMP R0,#EOF ; Check for end of file error
BNE 5$ ; If not then branch
RTS PC ; Return with error code
5$: $FETCH R0,RSZ,R1 ; Get the record size and put it in R0
MOV R0,BUCOUNT ; Save the record size
CLR R0 ; Clear the pointer
CLR RDCOUNT ; . . .
10$: MOVB RDBUF(R0),R0 ; Get the next character
INC RDCOUNT ; Increment the offset into the buffer
BIC #LEFTBYTE,R0 ; Clear high order byte of R0
RTS PC ; Return to sender
.SBTTL Buffer a character of the data line
;++
; Buffer the character in R0
;--
BUFFER: MOV R0,-(SP) ; Save the character on the stack
MOV WTCOUNT,R0 ; Get the offset into the buffer
MOVB (SP)+,WTBUF(R0) ; Move the character to the buffer
INC WTCOUNT ; Increment the pointer
BUFRTS: RTS PC ; Return to sender
.SBTTL Put a record to the file
;++
;Write the record
;--
PUT:
MOV WTCOUNT,R0 ; Get the count
MOV #WTRAB,R1 ; Get the RAB address
$STORE R0,RSZ,R1 ; Put its size into the RAB.
$PUT R1 ; Output the record
JSR PC,RMSERR ; Check for file error
CLR WTCOUNT ; Clear the counter for next record
RTS PC ; Return
.SBTTL Convert to Hexadecimal ASCII digits
;++
; Convert a word to 2 ASCII hexadecimal digits
;--
CVTHEX:
TST R0 ; See if this is a null
BNE CVTH ; If not then just branch
INC NULCOUNT ; A null so just increment the count
RTS PC ; for later and leave
; Convert a word to 2 ASCII hexadecimal digits without null compression
CVTH: MOV R0,-(SP) ; Save the character on the stack
10$: TST NULCOUNT ; Check to see if there are nulls
BEQ 20$ ; If not then just branch
CLR R0 ; Put a null in R0
JSR PC,CVT1 ; Put the null in the buffer
DEC NULCOUNT ; Decrement null counter
BR 10$ ; Repeat
20$: MOV (SP)+,R0 ; Get the original value back
CVT1: ADD R0,CHKSUM ; Add the value to the checksum
MOV R0,R1 ; Save the value
BIC #17+LEFTBYTE,R0 ; Leave only left Hex digit
ASH #-4,R0 ; Shift right to get first digit
JSR PC,HEX ; in place and convert to Hex
JSR PC,BUFFER ; Buffer the Hex character
MOV R1,R0 ; Get the original value back
BIC #17*20+LEFTBYTE,R0 ; Get right Hex digit
JSR PC,HEX ; Convert to Hex
JSR PC,BUFFER ; Buffer the Hex character
RTS PC ; Return to sender
HEX: MOV R0,R2 ; Move the base to R2
CMP R2,#9. ; Check to see if above '9
BLE 1$ ; If not then branch
ADD #HEXOFFSET,R0 ; Add offset to alphabet
1$: ADD #48.,R0 ; Make ASCII
RTS PC ; Return to sender
.SBTTL End of Hexify
.END HEXIFY