Skip to content

Instantly share code, notes, and snippets.

@polyrabbit
Last active August 17, 2018 15:55
Show Gist options
  • Save polyrabbit/81d57686eebe9bc5a9cc530397ff9d04 to your computer and use it in GitHub Desktop.
Save polyrabbit/81d57686eebe9bc5a9cc530397ff9d04 to your computer and use it in GitHub Desktop.
Decode from EBCDIC CodePage1047(IBM-1047) to UTF-8
// The decode method is copied from here:
// https://github.com/zos-go/go/blob/68b2cb8fee417890683b7fa01f02969d0900ff28/src/internal/ebcdic/ebcdic.go
// MCX - Add main function to call the Decode method, so I can view EBCDIC text outside z/OS
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"io/ioutil"
"os"
)
const (
RuneError = '\uFFFD'
)
var codePage1047 map[byte]rune
func init() {
codePage1047 = map[byte]rune{
0x00: '\x00',
0x01: '\x01',
0x02: '\x02',
0x03: '\x03',
0x04: RuneError,
0x05: '\t',
0x06: RuneError,
0x07: '\x7f',
0x08: RuneError,
0x09: RuneError,
0x0a: RuneError,
0x0b: '\x0b',
0x0c: '\x0c',
0x0d: '\x0d',
0x0e: '\x0e',
0x0f: '\x0f',
0x10: '\x10',
0x11: '\x11',
0x12: '\x12',
0x13: '\x13',
0x14: RuneError,
0x15: '\x0a',
0x16: '\x08',
0x17: RuneError,
0x18: '\x18',
0x19: '\x19',
0x1a: RuneError,
0x1b: RuneError,
0x1c: '\x1c',
0x1d: '\x1d',
0x1e: '\x1e',
0x1f: '\x1f',
0x20: RuneError,
0x21: RuneError,
0x22: RuneError,
0x23: RuneError,
0x24: RuneError,
0x25: '\n',
0x26: '\x17',
0x27: '\x1b',
0x28: RuneError,
0x29: RuneError,
0x2a: RuneError,
0x2b: RuneError,
0x2c: RuneError,
0x2d: '\x05',
0x2e: '\x06',
0x2f: '\x07',
0x30: RuneError,
0x31: RuneError,
0x32: '\x16',
0x33: RuneError,
0x34: RuneError,
0x35: RuneError,
0x36: RuneError,
0x37: '\x04',
0x38: RuneError,
0x39: RuneError,
0x3a: RuneError,
0x3b: RuneError,
0x3c: '\x14',
0x3d: '\x15',
0x3e: RuneError,
0x3f: '\x1a',
0x40: ' ',
0x41: '\xa0',
0x42: RuneError,
0x43: RuneError,
0x44: RuneError,
0x45: RuneError,
0x46: RuneError,
0x47: RuneError,
0x48: RuneError,
0x49: RuneError,
0x4a: RuneError,
0x4b: '.',
0x4c: '<',
0x4d: '(',
0x4e: '+',
0x4f: '|',
0x50: '&',
0x51: RuneError,
0x52: RuneError,
0x53: RuneError,
0x54: RuneError,
0x55: RuneError,
0x56: RuneError,
0x57: RuneError,
0x58: RuneError,
0x59: RuneError,
0x5a: '!',
0x5b: '$',
0x5c: '*',
0x5d: ')',
0x5e: ';',
0x5f: '¬',
0x60: '-',
0x61: '/',
0x62: RuneError,
0x63: RuneError,
0x64: RuneError,
0x65: RuneError,
0x66: RuneError,
0x67: RuneError,
0x68: RuneError,
0x69: RuneError,
0x6a: '¦',
0x6b: ',',
0x6c: '%',
0x6d: '_',
0x6e: '>',
0x6f: '?',
0x70: RuneError,
0x71: RuneError,
0x72: RuneError,
0x73: RuneError,
0x74: RuneError,
0x75: RuneError,
0x76: RuneError,
0x77: RuneError,
0x78: RuneError,
0x79: '`',
0x7a: ':',
0x7b: '#',
0x7c: '@',
0x7d: '\'',
0x7e: '=',
0x7f: '"',
0x80: RuneError,
0x81: 'a',
0x82: 'b',
0x83: 'c',
0x84: 'd',
0x85: 'e',
0x86: 'f',
0x87: 'g',
0x88: 'h',
0x89: 'i',
0x8a: RuneError,
0x8b: RuneError,
0x8c: RuneError,
0x8d: RuneError,
0x8e: RuneError,
0x8f: '±',
0x90: RuneError,
0x91: 'j',
0x92: 'k',
0x93: 'l',
0x94: 'm',
0x95: 'n',
0x96: 'o',
0x97: 'p',
0x98: 'q',
0x99: 'r',
0x9a: RuneError,
0x9b: RuneError,
0x9c: RuneError,
0x9d: RuneError,
0x9e: RuneError,
0x9f: RuneError,
0xa0: RuneError,
0xa1: '~',
0xa2: 's',
0xa3: 't',
0xa4: 'u',
0xa5: 'v',
0xa6: 'w',
0xa7: 'x',
0xa8: 'y',
0xa9: 'z',
0xaa: RuneError,
0xab: RuneError,
0xac: RuneError,
0xad: RuneError,
0xae: RuneError,
0xaf: RuneError,
0xb0: '^',
0xb1: RuneError,
0xb2: RuneError,
0xb3: RuneError,
0xb4: RuneError,
0xb5: RuneError,
0xb6: RuneError,
0xb7: RuneError,
0xb8: RuneError,
0xb9: RuneError,
0xba: '[',
0xbb: ']',
0xbc: RuneError,
0xbd: RuneError,
0xbe: RuneError,
0xbf: RuneError,
0xc0: '{',
0xc1: 'A',
0xc2: 'B',
0xc3: 'C',
0xc4: 'D',
0xc5: 'E',
0xc6: 'F',
0xc7: 'G',
0xc8: 'H',
0xc9: 'I',
0xca: '\xad',
0xcb: RuneError,
0xcc: RuneError,
0xcd: RuneError,
0xce: RuneError,
0xcf: RuneError,
0xd0: '}',
0xd1: 'J',
0xd2: 'K',
0xd3: 'L',
0xd4: 'M',
0xd5: 'N',
0xd6: 'O',
0xd7: 'P',
0xd8: 'Q',
0xd9: 'R',
0xda: RuneError,
0xdb: RuneError,
0xdc: RuneError,
0xdd: RuneError,
0xde: RuneError,
0xdf: RuneError,
0xe0: '\\',
0xe1: '\u2007',
0xe2: 'S',
0xe3: 'T',
0xe4: 'U',
0xe5: 'V',
0xe6: 'W',
0xe7: 'X',
0xe8: 'Y',
0xe9: 'Z',
0xea: RuneError,
0xeb: RuneError,
0xec: RuneError,
0xed: RuneError,
0xee: RuneError,
0xef: RuneError,
0xf0: '0',
0xf1: '1',
0xf2: '2',
0xf3: '3',
0xf4: '4',
0xf5: '5',
0xf6: '6',
0xf7: '7',
0xf8: '8',
0xf9: '9',
0xfa: RuneError,
0xfb: RuneError,
0xfc: RuneError,
0xfd: RuneError,
0xfe: RuneError,
0xff: RuneError,
}
}
// Decode from EBCDIC CodePage1047 to UTF-8
func Decode(src []byte) ([]rune, string) {
if len(src) == 0 {
return nil, string("")
}
dst := make([]rune, 0)
for _, c := range src {
e, ok := codePage1047[c]
if !ok {
return nil, string("unknown EBCDIC code")
}
dst = append(dst, e)
}
return dst, string("")
}
func main() {
if len(os.Args) < 2 {
fmt.Printf("Usage: %s input_EBCDIC_file <output_UTF8_file>\n", os.Args[0])
os.Exit(0)
}
var (
outWriter = os.Stdout
err error
)
if len(os.Args) >= 3 {
if outWriter, err = os.Create(os.Args[2]); err != nil {
panic(err)
}
defer outWriter.Close()
}
ebcdicText, err := ioutil.ReadFile(os.Args[1])
if err != nil {
panic(err)
}
outputRune, errStr := Decode(ebcdicText)
if errStr != "" {
panic(err)
}
fmt.Fprint(outWriter, string(outputRune))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment