73 lines
2.6 KiB
Python
73 lines
2.6 KiB
Python
from dataclasses import dataclass
|
|
|
|
EBCDIC_037 = {
|
|
0x40: ' ', 0x4B: '.', 0x4C: '<', 0x4D: '(', 0x4E: '+', 0x5A: '!', 0x5B: '$',
|
|
0x5C: '*', 0x5D: ')', 0x5E: ';', 0x60: '-', 0x61: '/', 0x6B: ',', 0x6C: '%',
|
|
0x6D: '_', 0x6E: '>', 0x6F: '?', 0x7A: ':', 0x7B: '#', 0x7C: '@', 0x7D: "'",
|
|
0x7E: '=', 0x7F: '"',
|
|
0x81: 'a', 0x82: 'b', 0x83: 'c', 0x84: 'd', 0x85: 'e', 0x86: 'f', 0x87: 'g',
|
|
0x88: 'h', 0x89: 'i', 0x91: 'j', 0x92: 'k', 0x93: 'l', 0x94: 'm', 0x95: 'n',
|
|
0x96: 'o', 0x97: 'p', 0x98: 'q', 0x99: 'r', 0xA2: 's', 0xA3: 't', 0xA4: 'u',
|
|
0xA5: 'v', 0xA6: 'w', 0xA7: 'x', 0xA8: 'y', 0xA9: 'z',
|
|
0xC1: 'A', 0xC2: 'B', 0xC3: 'C', 0xC4: 'D', 0xC5: 'E', 0xC6: 'F', 0xC7: 'G',
|
|
0xC8: 'H', 0xC9: 'I', 0xD1: 'J', 0xD2: 'K', 0xD3: 'L', 0xD4: 'M', 0xD5: 'N',
|
|
0xD6: 'O', 0xD7: 'P', 0xD8: 'Q', 0xD9: 'R', 0xE2: 'S', 0xE3: 'T', 0xE4: 'U',
|
|
0xE5: 'V', 0xE6: 'W', 0xE7: 'X', 0xE8: 'Y', 0xE9: 'Z',
|
|
0xF0: '0', 0xF1: '1', 0xF2: '2', 0xF3: '3', 0xF4: '4', 0xF5: '5',
|
|
0xF6: '6', 0xF7: '7', 0xF8: '8', 0xF9: '9',
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class CobolIRField:
|
|
raw_hex: str; decoded_value: str; encoding: str
|
|
field_type: str; length: int; scale: int; signed: bool
|
|
|
|
|
|
@dataclass
|
|
class JavaIRField:
|
|
raw_value: str; decoded_value: str; field_type: str; nullable: bool
|
|
|
|
|
|
@dataclass
|
|
class IRRecord:
|
|
field_name: str
|
|
cobol: CobolIRField | None = None
|
|
java: JavaIRField | None = None
|
|
|
|
|
|
class Normalizer:
|
|
def normalize_encoding(self, raw: bytes, encoding: str) -> str:
|
|
if encoding == "EBCDIC":
|
|
return "".join(EBCDIC_037.get(b, chr(b) if 32 <= b < 127 else "?") for b in raw)
|
|
return raw.decode("ascii", errors="replace")
|
|
|
|
def normalize_comp3(self, raw: bytes) -> str:
|
|
if not raw:
|
|
return "0"
|
|
nibbles = []
|
|
for b in raw:
|
|
nibbles.append((b >> 4) & 0x0F)
|
|
nibbles.append(b & 0x0F)
|
|
sign = nibbles.pop()
|
|
v = 0
|
|
for n in nibbles:
|
|
v = v * 10 + (n if n <= 9 else 0)
|
|
if sign in (0x0D, 0x0B):
|
|
v = -v
|
|
return str(v)
|
|
|
|
def normalize_date(self, s: str) -> str:
|
|
s = s.strip()
|
|
if len(s) == 8 and s.isdigit():
|
|
return f"{s[:4]}-{s[4:6]}-{s[6:8]}"
|
|
return s
|
|
|
|
def to_ir_record(self, name, hex_, val, enc, ft, length=0, scale=0, signed=False):
|
|
return IRRecord(name, CobolIRField(hex_, val, enc, ft, length, scale, signed))
|
|
|
|
def to_null_ir(self, name, side="java"):
|
|
if side == "java":
|
|
return IRRecord(name, java=JavaIRField("", "", "null", True))
|
|
return IRRecord(name, java=JavaIRField("", "", "null", True))
|