home *** CD-ROM | disk | FTP | other *** search
- # Macros to display signed decimal numbers in two's complement hexadecimal
- # notation. Because the code underlying most of Kermit's arithmetic and
- # numeric comparison functions uses machine arithmetic, it is necessary to
- # employ string operations and lexical comparisons to handle edge cases.
- # Works in both C-Kermit (8.0 and later) and K95 (2.0 and later).
- #
- # F. da Cruz, Columbia University, 19 November 2007
-
- # Macro BINTOHEX converts a binary string to hex.
- # \%1 = binary number (string)
- # \%2 = word size in bits
- #
- # \fradix() is constrained by machine integer word length
- # so we do it in pieces in case the number is too big.
- #
- define BINTOHEX {
- undef \%6 # Result accumulator
- for \%9 1 \%2 4 { # Do four bits at at a time
- .\%8 := \fsubstr(\%1,\%9,4) # Get chunk of 4
- if not def \%8 break # Make sure we have one
- .\%7 := \fradix(\%8,2,16) # Convert to Hex digit
- .\%6 := \%6\%7 # Accumulate
- }
- return \%6
- }
- # Macro DECTOHEX converts a signed decimal number to 2's complement hex.
- # \%1 = decimal number string (default 0)
- # \%2 = word size in bits (must be a power of two, 4 or greater, default 32)
- #
- # Because of how \fradix() works, this function operates correctly only
- # for numbers whose absolute value fits in the machine's integer word.
- #
- define DECTOHEX {
- local m1
- if not def \%1 .\%1 = 0 # Supply default if no arg given
- if not numeric \%1 return NOT_A_NUMBER:\%1 # Check that arg is a number
- if not def \%2 .\%2 := 32 # Use 32 bits if no second arg
- (setq m1 (truncate (- (^ 2 (- \%2 1)) 1))) # Largest positive number
- if eq "\fsubstr(\%1,1,1)" "+" .\%1 := \fsubstr(\%1,2) # strip any + sign
- if not eq "\fsubstr(\%1,1,1)" "-" { # Argument is signed?
- .\%1 := \flpad(\%1,\flen(\v(svalue)),0) # No - check magnitude
- if lgt \%1 \v(svalue) return OVERFLOW
- return \flpad(\fradix(\%1,10,16),(\%2 / 4),0) # Convert to hex and pad
- }
- .\%1 := \fsubstr(\%1,2) # Negative number - remove sign
- .\%1 := \flpad(\%1,\flen(\m(m1)),0) # Must use lexical comparison
- (++ m1) # Avoid fencepost error
- if llt \m(m1) \%1 return UNDERFLOW # Check magnitude
- .\%9 := \flpad(\fradix(\%1,10,2),\%2,0) # Convert to binary and pad
- .\%8 ::= \frindex(1,\%9) - 1 # Find first 1 on the right
- if == \%8 -1 { # Watch out for negative 0
- return \frepeat(0,\%2 / 4)
- }
- .\%7 := \fsubstr(\%9,1,\%8) # Split string here
- .\%6 := \fsubstitute(\%7,01,10) # Complement bits in left part
- .\%5 := \%6\fsubstr(\%9,\%8+1) # Put back with right part
- .\%4 := \fexec(bintohex \%5 \%2) # Convert to hex
- return \%4
- }
- # Test the functions...
-
- set take echo on
- echo \fexec(dectohex 7) # No word size specified
- echo \fexec(dectohex)
-
- echo \fexec(dectohex 7 4) # 4-bit word
- echo \fexec(dectohex 8 4)
- echo \fexec(dectohex -8 4)
- echo \fexec(dectohex -9 4)
- echo \fexec(dectohex 99 4)
-
- echo \fexec(dectohex 0 8) # 8-bit word
- echo \fexec(dectohex -0 8)
- echo \fexec(dectohex 1 8)
- echo \fexec(dectohex +1 8)
- echo \fexec(dectohex 2 8)
- echo \fexec(dectohex 3 8)
- echo \fexec(dectohex 4 8)
- echo \fexec(dectohex 5 8)
- echo \fexec(dectohex 6 8)
- echo \fexec(dectohex 7 8)
- echo \fexec(dectohex -1 8)
- echo \fexec(dectohex -2 8)
- echo \fexec(dectohex -3 8)
- echo \fexec(dectohex -4 8)
- echo \fexec(dectohex -5 8)
- echo \fexec(dectohex -6 8)
- echo \fexec(dectohex -7 8)
- echo \fexec(dectohex -8 8)
- echo \fexec(dectohex 64 8)
- echo \fexec(dectohex 65 8)
- echo \fexec(dectohex -128 8)
-
- echo \fexec(dectohex 0 16) # 16-bit word
- echo \fexec(dectohex 64 16)
- echo \fexec(dectohex 65 16)
- echo \fexec(dectohex -128 16)
- echo \fexec(dectohex -32768 16)
- echo \fexec(dectohex 99999 16)
- echo \fexec(dectohex -99999 16)
-
- echo \fexec(dectohex 0 32) # 32-bit word
- echo \fexec(dectohex 1 32)
- echo \fexec(dectohex 16383 32)
- echo \fexec(dectohex 2147483647 32)
- echo \fexec(dectohex -1 32)
- echo \fexec(dectohex -2 32)
- echo \fexec(dectohex -2147483647 32)
- echo \fexec(dectohex -2147483648 32)
-
- echo \fexec(dectohex 0 64) # 64-bit word
- echo \fexec(dectohex 2147483647 64)
- echo \fexec(dectohex -1 64)
- echo \fexec(dectohex -2 64)
- echo \fexec(dectohex -2147483647 64)
- echo \fexec(dectohex -2147483648 64)
-
- echo \fexec(dectohex 0 128) # 128-bit word
- echo \fexec(dectohex 1 128)
- echo \fexec(dectohex -1 128)
- echo \fexec(dectohex -2 128)
-
- set take echo off
- if c-kermit exit
-