Initial commit: COBOL+JCL credit card billing system with COMP-3, OCCURS, COPY REPLACING, INSPECT, and JCL runner
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
"""
|
||||
COMP-3 Packed Decimal Verification for COBOL Migration Platform.
|
||||
Validates that binary COMP-3 fields in RATE.dat are correctly encoded.
|
||||
|
||||
Usage: python verify_comp3.py
|
||||
|
||||
COMP-3 format: each byte holds 2 nibbles (4-bit digits),
|
||||
last nibble = sign (0xC/0xF = positive, 0xD = negative).
|
||||
PIC 9(1)V9(4) = 5 digits + sign = 3 bytes.
|
||||
"""
|
||||
|
||||
import struct
|
||||
import sys
|
||||
|
||||
|
||||
def unpack_comp3(data: bytes) -> tuple[int, int, str]:
|
||||
"""Unpack COMP-3 bytes -> (integer_value, decimal_places, sign)."""
|
||||
nibbles = []
|
||||
for byte in data:
|
||||
nibbles.append((byte >> 4) & 0x0F)
|
||||
nibbles.append(byte & 0x0F)
|
||||
|
||||
sign_nibble = nibbles[-1]
|
||||
digit_nibbles = nibbles[:-1]
|
||||
|
||||
value = 0
|
||||
for n in digit_nibbles:
|
||||
value = value * 10 + n
|
||||
|
||||
if sign_nibble in (0xC, 0xF):
|
||||
sign = "positive"
|
||||
elif sign_nibble == 0xD:
|
||||
sign = "negative"
|
||||
else:
|
||||
sign = f"unknown(0x{sign_nibble:X})"
|
||||
|
||||
return value, sign, data.hex()
|
||||
|
||||
|
||||
def main():
|
||||
rate_path = "D:/jcl-cobol/data/input/rate.dat"
|
||||
|
||||
with open(rate_path, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
rec_size = 12 # PIC X(1) + PIC 9(1)V9(4) COMP-3(3) + PIC 9(8)
|
||||
num_records = len(data) // rec_size
|
||||
|
||||
print(f"File: {rate_path}")
|
||||
print(f"Size: {len(data)} bytes")
|
||||
print(f"Records: {num_records}")
|
||||
print()
|
||||
|
||||
expected = {
|
||||
"C": ("Cash rate", 0.0005),
|
||||
"O": ("Overdue rate", 0.0500),
|
||||
}
|
||||
|
||||
all_ok = True
|
||||
|
||||
for i in range(num_records):
|
||||
offset = i * rec_size
|
||||
rec = data[offset : offset + rec_size]
|
||||
|
||||
rate_type = chr(rec[0])
|
||||
pct_bytes = rec[1:4]
|
||||
eff_date = rec[4:12].decode("ascii")
|
||||
|
||||
value, sign, pct_hex = unpack_comp3(pct_bytes)
|
||||
int_part = value // 10000
|
||||
dec_part = value % 10000
|
||||
pct_float = int_part + dec_part / 10000
|
||||
|
||||
name, expected_val = expected.get(rate_type, ("Unknown", None))
|
||||
|
||||
match = abs(pct_float - expected_val) < 0.0001 if expected_val else False
|
||||
status = "PASS" if match else "FAIL"
|
||||
if not match:
|
||||
all_ok = False
|
||||
|
||||
print(f"[{status}] Record {i+1}: type={rate_type} ({name})")
|
||||
print(f" COMP-3 hex: {pct_hex}")
|
||||
print(f" packed int: {value}")
|
||||
print(f" float val: {pct_float:.4f}")
|
||||
print(f" expected: {expected_val}")
|
||||
print(f" eff date: {eff_date}")
|
||||
print()
|
||||
|
||||
if all_ok:
|
||||
print("=== ALL COMP-3 VALUES VERIFIED ===")
|
||||
else:
|
||||
print("=== COMP-3 MISMATCH DETECTED ===")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user