On May 10, 2007, at 12:39 PM, Todd Burch wrote: > Here a whole program that illlustrates the error. I'm running under > Windows Ruby 1.8.5. (it's ugly and chopped up, but it works... er... > doesn't work... er... you know what I mean) > > Todd First, damn you for getting me interested in this ;-) Here's a whole program (with a couple tests!) that uses an array to map from an EBCDIC index to a single character ASCII string (easier to construct than the character value). I hope you find some useful idioms in there. -Rob Rob Biedenharn http://agileconsultingllc.com Rob / AgileConsultingLLC.com #!/usr/bin/env ruby -w # # Ruby program to convert a z/OS EBCDIC to ASCII. # class Record EBCDIC_TO_ASCII = Array.new(256) # the EBCDIC position holds the ASCII value EBCDIC_TO_ASCII[0x40] = ' ' EBCDIC_TO_ASCII[0x81..0x89] = [*'a'..'i'] EBCDIC_TO_ASCII[0x91..0x99] = [*'j'..'r'] EBCDIC_TO_ASCII[0xA2..0xA9] = [*'s'..'z'] EBCDIC_TO_ASCII[0xC1..0xC9] = [*'A'..'I'] EBCDIC_TO_ASCII[0xD1..0xD9] = [*'J'..'R'] EBCDIC_TO_ASCII[0xE2..0xE9] = [*'S'..'Z'] EBCDIC_TO_ASCII[0x4B] = '.' EBCDIC_TO_ASCII[0x4C] = '<' EBCDIC_TO_ASCII[0x4D] = '(' EBCDIC_TO_ASCII[0x4E] = '+' EBCDIC_TO_ASCII[0x4F] = '|' EBCDIC_TO_ASCII[0x50] = '&' EBCDIC_TO_ASCII[0x5A] = '!' EBCDIC_TO_ASCII[0x5B] = '$' EBCDIC_TO_ASCII[0x5C] = '*' EBCDIC_TO_ASCII[0x5D] = ')' EBCDIC_TO_ASCII[0x5E] = ';' EBCDIC_TO_ASCII[0x5F] = '^' EBCDIC_TO_ASCII[0x60] = '-' EBCDIC_TO_ASCII[0x61] = '/' EBCDIC_TO_ASCII[0x6B] = ',' EBCDIC_TO_ASCII[0x6C] = '%' EBCDIC_TO_ASCII[0x6D] = '_' EBCDIC_TO_ASCII[0x6E] = '>' EBCDIC_TO_ASCII[0x6F] = '?' EBCDIC_TO_ASCII[0X79] = '`' EBCDIC_TO_ASCII[0x7A] = ':' EBCDIC_TO_ASCII[0x7B] = '#' EBCDIC_TO_ASCII[0x7C] = '@' EBCDIC_TO_ASCII[0x7D] = '\'' EBCDIC_TO_ASCII[0x7E] = '=' EBCDIC_TO_ASCII[0x7F] = '"' EBCDIC_TO_ASCII[0xBA] = '[' EBCDIC_TO_ASCII[0xBB] = ']' EBCDIC_TO_ASCII[0xC0] = '{' EBCDIC_TO_ASCII[0xD0] = '}' EBCDIC_TO_ASCII[0xE0] = '\\' EBCDIC_TO_ASCII[0xF0..0xF9] = [*'0'..'9'] def self.to_ascii str str.split(//).map {|e| EBCDIC_TO_ASCII[e[0]] || 0.chr }.join end # This Record.to_h() method converts a hex byte into a displayable, human # readable value. i.e. X'F5' to "F5". # def self.to_h str, chunk=32 str.unpack('H*').first.scan(/.{2,#{2*chunk}}/).join("\n") end # # This method called to dump the data in hex format. # def self.dump_area data, chunk=16 fsize = data.size lines,last = fsize.divmod(chunk) # get # of full lines and figure the remainder. i = 0 lines.downto(0) do str = data[i,chunk] hexdata = str.unpack('H*').first.scan(/.{2,8}/).join(" ") #.upcase printf "%08X %s %s\n", i, hexdata, to_ascii(str).tr("\000- \037\177-\377",'.') i += chunk end end end if __FILE__ == $0 require 'test/unit' puts "EBCDIC Table" Record.dump_area((0...Record::EBCDIC_TO_ASCII.size).map{|e| e.chr}.join) class EbcdicTest < Test::Unit::TestCase def setup @instring_ascii = "AB>AA<AC" # EBCDIC for "AB>AA<AC" @instring_ebcdic = 0XC1.chr + 0xC2.chr + 0x6E.chr + 0xC1.chr + 0xC1.chr + 0x4C.chr + 0xC1.chr + 0xC3.chr end def test_simple assert_equal @instring_ascii, Record.to_ascii(@instring_ebcdic) end def test_numbers @expected = "$1,234.95" # $ 1 , 2 3 4 . 9 5 @input = [0x5B, 0xF1, 0x6B, 0xF2, 0xF3, 0xF4, 0x4B, 0xF9, 0xF5].map {|e| e.chr}.join assert_equal @expected, Record.to_ascii(@input) end end end __END__