Skip to main content

ironwork_rt/lir/
codec.rs

1//! Codecs for the types the LIR borrows from `rt`, `numeric` and `zarch`, with load-module.md's tags.
2
3use crate::abend::{AbendCode, Ending, FileStatus, LeCondition, Signal};
4use crate::files::Format;
5use crate::module::ModuleError;
6use crate::module::codec::{Decode, Encode, Reader, Writer};
7use crate::picture::Sym;
8use crate::sql::HostType;
9use crate::storage::Kind;
10use crate::vocab::{AcceptFrom, BinOp, Closing, Figurative, InspectMode, OpenMode, Pos, RelOp, SignClause, SignPosition};
11use crate::{codec_enum, codec_struct};
12use numeric::precision::{Fixed, Places};
13use numeric::options::{Assumed, Compile, Compliance, FastsrtAdvPrint, Invdata, LeServices, ProgramScope, SWITCHES, Stop, UnresolvedCalls, Warnings};
14use numeric::{
15    Arith, Native, BinCheck, CicsReturnWarning, Currency, Dialect, DispSign, Initcheck, IntDate, Nsymbol, Numcheck, Numproc, Options, Parmcheck, Qualify, Quote, SortKeys, Trunc,
16    TruncCheck, Vlr, VsamOpenFs, ZonCheck,
17};
18use zarch::check::ProgramCheck;
19use zarch::ebcdic::CodePage;
20use zarch::hfp::Precision;
21use zarch::wide::U256;
22
23codec_enum!(Kind {
24    Group = 0,
25    Alnum { justified } = 1,
26    National = 2,
27    Zoned { digits, scale, signed, sign } = 3,
28    Packed { digits, scale, signed } = 4,
29    Binary { digits, scale, signed, native } = 5,
30    Float(precision) = 6,
31    NumericEdited { edit, digits, scale, blank_when_zero } = 7,
32    AlnumEdited { edit } = 8,
33    Pointer = 9,
34    Index = 10,
35    ObjectReference = 11,
36    ProgramPointer = 12,
37    Dbcs { justified, edit } = 13,
38});
39codec_enum!(Native { No = 0, Comp5 = 1, BinaryChar = 2, CompX = 3, Comp5Bytes = 4 });
40codec_struct!(SignClause { position, separate });
41codec_struct!(Pos { file, line, col });
42codec_enum!(SignPosition { Leading = 0, Trailing = 1 });
43codec_enum!(Figurative { Zero = 0, Space = 1, HighValue = 2, LowValue = 3, Quote = 4, Null = 5 });
44codec_enum!(BinOp { Add = 0, Sub = 1, Mul = 2, Div = 3, Pow = 4 });
45codec_enum!(RelOp { Eq = 0, Ne = 1, Lt = 2, Le = 3, Gt = 4, Ge = 5 });
46codec_enum!(AcceptFrom {
47    Sysin = 0,
48    Date { four_digit_year } = 1,
49    Day { four_digit_year } = 2,
50    DayOfWeek = 3,
51    Time = 4,
52    CommandLine = 5,
53    ArgumentNumber = 6,
54    ArgumentValue = 7,
55    EnvironmentValue = 8,
56});
57codec_enum!(InspectMode { Characters = 0, All = 1, Leading = 2, First = 3, Trailing = 4 });
58codec_enum!(OpenMode { Input = 0, Output = 1, Extend = 2, InputOutput = 3 });
59codec_enum!(Closing { Volume = 0, NoRewind = 1, Lock = 2 });
60codec_enum!(Format { Fixed = 0, Variable = 1, Text = 2 });
61codec_enum!(HostType {
62    SmallInt { signed } = 0,
63    Integer { signed } = 1,
64    BigInt { signed } = 2,
65    Decimal { digits, scale, signed } = 3,
66    Zoned { digits, scale, signed, sign } = 4,
67    Real = 5,
68    Double = 6,
69    Char(len) = 7,
70    VarChar(max) = 8,
71    Structure(members) = 9,
72    Graphic(len) = 10,
73    VarGraphic(max) = 11,
74});
75codec_enum!(Sym {
76    Nine = 0,
77    Z = 1,
78    Star = 2,
79    FloatLead(c) = 3,
80    Float(c) = 4,
81    Sign(c) = 5,
82    Currency = 6,
83    Cr = 7,
84    Db = 8,
85    Point = 9,
86    Implied = 10,
87    Insert(c) = 11,
88    Char = 12,
89});
90codec_enum!(Precision { Short = 0, Long = 1, Extended = 2 });
91codec_enum!(ProgramCheck {
92    Specification = 0,
93    Data = 1,
94    FixedPointOverflow = 2,
95    FixedPointDivide = 3,
96    DecimalOverflow = 4,
97    DecimalDivide = 5,
98    HfpExponentOverflow = 6,
99    HfpExponentUnderflow = 7,
100    HfpSignificance = 8,
101    HfpDivide = 9,
102});
103
104codec_enum!(Ending { Goback = 0, StopRun = 1, EndOfProgram = 2 });
105codec_enum!(AbendCode {
106    Check(check) = 0,
107    Protection = 1,
108    ModuleNotFound = 2,
109    Io(status) = 3,
110    Cics(code) = 4,
111    User(code) = 5,
112    Ironwork = 6,
113    Exec = 7,
114    Sql = 8,
115    SqlReplay = 9,
116    Java = 10,
117    Signal(signal) = 11,
118    TimeLimit = 12,
119    Le(condition) = 13,
120    Requested { code, clean_up } = 14,
121});
122codec_enum!(LeCondition { ZeroPower = 0, FileStatus = 1 });
123codec_enum!(Signal { StopRun = 0, GoBack = 1, SortStopped = 2, ClosedOutput = 3, DeclarativeExit = 4 });
124codec_enum!(FileStatus {
125    Success = 0,
126    SuccessDuplicate = 1,
127    SuccessWrongLength = 2,
128    SuccessOptional = 3,
129    AtEnd = 4,
130    RelativeKeyOverflow = 5,
131    SequenceError = 6,
132    DuplicateKey = 7,
133    NotFound = 8,
134    BoundaryViolation = 9,
135    PermanentError = 10,
136    FileNotFound = 11,
137    OpenModeUnsupported = 12,
138    AlreadyOpen = 13,
139    NotOpen = 14,
140    NoPriorRead = 15,
141    RecordLengthChanged = 16,
142    NoNextRecord = 17,
143    NotOpenInput = 18,
144    NotOpenOutput = 19,
145    NotOpenInputOutput = 20,
146    SuccessNonReel = 21,
147    ClosedWithLock = 22,
148    SuccessVerified = 23,
149});
150
151codec_struct!(Options {
152    arith, trunc, numproc, codepage, trunc_check, fastsrt, fastsrt_adv_print, sort_keys, adv, thread, dll, rent, dbcs,
153    warnings, compile, dynam, debug, cics_return_warning, invdata, zwb, quote, currency, nsymbol, dispsign, intdate, qualify, initial,
154    vlr, vsamopenfs, numcheck, parmcheck, initcheck, optimize, compliance, dialect, program_scope, unresolved_calls, le_services,
155} default { assumed } check options_valid);
156codec_struct!(Invdata { forcenumcmp, cleansign });
157codec_enum!(Arith { Compat = 0, Extend = 1 });
158codec_enum!(Trunc { Std = 0, Opt = 1, Bin = 2 });
159codec_enum!(Numproc { Nopfd = 0, Pfd = 1 });
160codec_enum!(TruncCheck { Report = 0, Silent = 1 });
161codec_enum!(SortKeys { Dfsort = 0, Strict = 1 });
162codec_enum!(FastsrtAdvPrint { Exclude = 0, Include = 1 });
163codec_enum!(Warnings { Proceed = 0, Block = 1 });
164codec_enum!(Compile { Full = 0, Until(stop) = 1, SyntaxOnly = 2 });
165codec_enum!(Stop { W = 0, E = 1, S = 2 });
166codec_enum!(CicsReturnWarning { Once = 0, Always = 1, Never = 2 });
167codec_enum!(Quote { Quote = 0, Apost = 1 });
168codec_enum!(Currency { Char(c) = 0, Hex(b) = 1 });
169codec_enum!(Nsymbol { National = 0, Dbcs = 1 });
170codec_enum!(DispSign { Compat = 0, Sep = 1 });
171codec_enum!(IntDate { Ansi = 0, Lilian = 1 });
172codec_enum!(Qualify { Compat = 0, Extend = 1 });
173codec_enum!(Vlr { Standard = 0, Compat = 1 });
174codec_enum!(VsamOpenFs { Compat = 0, Succ = 1 });
175codec_enum!(Compliance { Strict = 0, Extended = 1 });
176codec_enum!(ProgramScope { Strict = 0, Flexible = 1 });
177codec_enum!(UnresolvedCalls { Run = 0, Fail = 1 });
178codec_enum!(LeServices { Programs = 0, Bind = 1 });
179codec_struct!(Numcheck { zon, pac, bin, abd });
180codec_struct!(ZonCheck { alphnum, lax });
181codec_struct!(BinCheck { truncbin });
182codec_struct!(Parmcheck { abd, bytes });
183codec_enum!(Initcheck { Lax = 0, Strict = 1 });
184codec_enum!(Dialect { Ibm = 0, Gnucobol = 1 });
185codec_struct!(Assumed { given } check assumed_valid);
186
187/// `Options::code_page` panics on a CCSID the tables do not carry, and OPTIMIZE has three levels.
188fn options_valid(options: &Options) -> Result<(), String> {
189    if options.optimize > 2 {
190        return Err(format!("OPTIMIZE({}) is not a level", options.optimize));
191    }
192    match CodePage::by_ccsid(options.codepage) {
193        Some(_) => Ok(()),
194        None => Err(format!("CODEPAGE({}) is not a page the tables carry", options.codepage)),
195    }
196}
197
198/// Each `--assume` mark names one of its switch's values.
199fn assumed_valid(assumed: &Assumed) -> Result<(), String> {
200    match SWITCHES.iter().zip(assumed.given).find(|((_, values), mark)| usize::from(*mark) > values.len()) {
201        Some(((id, _), mark)) => Err(format!("--assume value {mark} is not one {id} takes")),
202        None => Ok(()),
203    }
204}
205
206codec_struct!(Fixed { negative, magnitude, places });
207codec_struct!(Places { int, dec });
208
209/// Four 64-bit limbs, low first.
210impl Encode for U256 {
211    fn encode(&self, w: &mut Writer) {
212        [self.lo as u64, (self.lo >> 64) as u64, self.hi as u64, (self.hi >> 64) as u64].encode(w);
213    }
214}
215
216impl Decode for U256 {
217    fn decode(r: &mut Reader<'_>) -> Result<Self, ModuleError> {
218        let [a, b, c, d] = <[u64; 4]>::decode(r)?;
219        let limbs = |low: u64, high: u64| u128::from(low) | u128::from(high) << 64;
220        Ok(U256 { hi: limbs(c, d), lo: limbs(a, b) })
221    }
222}