1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2pub enum Oracle {
3 Hercules,
5 EnterpriseCobol,
7}
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum Basis {
11 Documented,
13 Recalled,
15 Chosen,
17}
18
19#[derive(Clone, Copy, Debug)]
20pub struct Assumption {
21 pub id: &'static str,
22 pub claim: &'static str,
23 pub basis: Basis,
24 pub oracle: Oracle,
25}
26
27pub const HFP_EXTENDED_LOW_HALF: &str = "M1";
28pub const HFP_FROM_FIXED_TRUNCATES: &str = "M2";
29pub const INTERMEDIATE_TABLE: &str = "C1";
30pub const TRUNC_OPT_IS_BINARY: &str = "C2";
31pub const PFD_MOVES_BYTES: &str = "C3";
32pub const PFD_COMPARES_LOGICALLY: &str = "C4";
33pub const FLOAT_FROM_DECIMAL: &str = "C5";
34pub const FLOAT_TO_DECIMAL: &str = "C6";
35pub const FLOAT_NARROWING_TRUNCATES: &str = "C7";
36pub const LE_MASKS_UNDERFLOW: &str = "C8";
37pub const PREFERRED_RESULT_SIGNS: &str = "C9";
38pub const ZONED_BY_PACK: &str = "C10";
39pub const CCSID_TABLES: &str = "C11";
40pub const WORKING_STORAGE_LAYOUT: &str = "C12";
41pub const NOPFD_REPAIRS_UNSIGNED_INPUT: &str = "C13";
42pub const DISPLAY_OF_NONDISPLAY_NUMERIC: &str = "C14";
43pub const ACCEPT_AT_END: &str = "C15";
44pub const CONTENT_LITERAL_ZONED: &str = "C16";
45pub const KEYED_FILE_STATUS: &str = "C17";
46pub const ALTERNATE_KEY_ORDER: &str = "C18";
47pub const FAILED_READ_LOSES_POSITION: &str = "C19";
48pub const START_COMPARES_SHORTER: &str = "C20";
49pub const REWRITE_SHARED_ALTERNATE: &str = "C21";
50pub const CICS_FRESH_STORAGE: &str = "C22";
51pub const CICS_CALEN_RESTORED: &str = "C23";
52pub const CICS_HANDLE_ABEND_CATCHES_CONDITIONS: &str = "C24";
53pub const CICS_LENGTH_DEFAULTS_TO_INTO: &str = "C25";
54pub const CICS_PROGRAM_CHECK_IS_ASRA: &str = "C26";
55pub const CICS_BROWSE_SKIP: &str = "C27";
56pub const BMS_RECEIVE_NULLS: &str = "C28";
57pub const BMS_INPUT_JUSTIFY: &str = "C29";
58pub const BMS_EXTENDED_ORDER: &str = "C30";
59pub const BMS_CONSTANTS_UNVERIFIED: &str = "C31";
60pub const BMS_SEND_DATA_CHOICE: &str = "C32";
61pub const CICS_INITIAL_AID: &str = "C33";
62
63pub const ASSUMPTIONS: &[Assumption] = &[
64 Assumption {
65 id: HFP_EXTENDED_LOW_HALF,
66 claim: "An extended HFP result's low half carries the high characteristic minus 14, modulo 128, and is all zero when the value is all zero bits (SA22-7832-14, HFP extended format, p. 18-4)",
67 basis: Basis::Documented,
68 oracle: Oracle::Hercules,
69 },
70 Assumption {
71 id: HFP_FROM_FIXED_TRUNCATES,
72 claim: "CONVERT FROM FIXED to HFP truncates the hexadecimal digits the precision cannot hold",
73 basis: Basis::Recalled,
74 oracle: Oracle::Hercules,
75 },
76 Assumption {
77 id: INTERMEDIATE_TABLE,
78 claim: "Intermediate results carry i and d places up to 30 digits (31 under ARITH(EXTEND)); beyond that, N-d and d when d <= dmax, else i and N-i when i+dmax <= N, else N-dmax and dmax; digits beyond are truncated",
79 basis: Basis::Recalled,
80 oracle: Oracle::EnterpriseCobol,
81 },
82 Assumption {
83 id: TRUNC_OPT_IS_BINARY,
84 claim: "Under TRUNC(OPT) a binary receiver whose value exceeds its PICTURE is truncated at the halfword, fullword or doubleword, as under TRUNC(BIN)",
85 basis: Basis::Chosen,
86 oracle: Oracle::EnterpriseCobol,
87 },
88 Assumption {
89 id: PFD_MOVES_BYTES,
90 claim: "Under NUMPROC(PFD) a MOVE between packed items of the same length and scale copies the bytes, so a non-preferred sign passes through; under NOPFD the receiver gets the preferred sign",
91 basis: Basis::Chosen,
92 oracle: Oracle::EnterpriseCobol,
93 },
94 Assumption {
95 id: PFD_COMPARES_LOGICALLY,
96 claim: "Under NUMPROC(PFD) two packed items of the same length and scale compare byte by byte, so X'1F' and X'1C' differ",
97 basis: Basis::Chosen,
98 oracle: Oracle::EnterpriseCobol,
99 },
100 Assumption {
101 id: FLOAT_FROM_DECIMAL,
102 claim: "A fixed-point decimal m with s decimal places becomes HFP as CONVERT FROM FIXED of m, then an HFP divide by 10^s",
103 basis: Basis::Chosen,
104 oracle: Oracle::EnterpriseCobol,
105 },
106 Assumption {
107 id: FLOAT_TO_DECIMAL,
108 claim: "An HFP value moved to a fixed-point receiver is its exact value truncated at the receiver's scale, or rounded half away from zero under ROUNDED",
109 basis: Basis::Chosen,
110 oracle: Oracle::EnterpriseCobol,
111 },
112 Assumption {
113 id: FLOAT_NARROWING_TRUNCATES,
114 claim: "A floating-point intermediate stored into a narrower COMP-1 or COMP-2 keeps its high-order part (truncation), not LOAD ROUNDED",
115 basis: Basis::Chosen,
116 oracle: Oracle::EnterpriseCobol,
117 },
118 Assumption {
119 id: LE_MASKS_UNDERFLOW,
120 claim: "Language Environment runs COBOL with the HFP exponent-underflow and significance masks off, so both yield a true zero",
121 basis: Basis::Chosen,
122 oracle: Oracle::EnterpriseCobol,
123 },
124 Assumption {
125 id: PREFERRED_RESULT_SIGNS,
126 claim: "Arithmetic results take the preferred sign under either NUMPROC setting: C or D for a signed item, F for an unsigned one",
127 basis: Basis::Recalled,
128 oracle: Oracle::EnterpriseCobol,
129 },
130 Assumption {
131 id: ZONED_BY_PACK,
132 claim: "A zoned operand enters arithmetic as PACK leaves it: zones other than the sign's are discarded, so an embedded space is a zero digit",
133 basis: Basis::Chosen,
134 oracle: Oracle::EnterpriseCobol,
135 },
136 Assumption {
137 id: CCSID_TABLES,
138 claim: "The compiler's conversion to UTF-16 for each carried CCSID is ICU's ibm-* table for it, byte for byte",
139 basis: Basis::Chosen,
140 oracle: Oracle::EnterpriseCobol,
141 },
142 Assumption {
143 id: WORKING_STORAGE_LAYOUT,
144 claim: "Each 01 and 77 item of WORKING-STORAGE starts on an 8-byte boundary in source order, and storage without a VALUE starts as X'00'",
145 basis: Basis::Chosen,
146 oracle: Oracle::EnterpriseCobol,
147 },
148 Assumption {
149 id: NOPFD_REPAIRS_UNSIGNED_INPUT,
150 claim: "Under NUMPROC(NOPFD) an unsigned packed or zoned operand's sign is forced to X'F' before use, so no sign makes it a data exception; under PFD it is used as it stands",
151 basis: Basis::Chosen,
152 oracle: Oracle::EnterpriseCobol,
153 },
154 Assumption {
155 id: DISPLAY_OF_NONDISPLAY_NUMERIC,
156 claim: "DISPLAY shows a packed or binary item as zoned digits of its PICTURE, with the sign overpunched on the last digit when the item is signed; a COMP-5 item, or any binary item under TRUNC(BIN), shows its whole binary value in 5, 10, or 19 (signed) or 20 digits for a halfword, fullword or doubleword",
157 basis: Basis::Chosen,
158 oracle: Oracle::EnterpriseCobol,
159 },
160 Assumption {
161 id: ACCEPT_AT_END,
162 claim: "ACCEPT from SYSIN at its end leaves the receiving item unchanged and the run continues",
163 basis: Basis::Chosen,
164 oracle: Oracle::EnterpriseCobol,
165 },
166 Assumption {
167 id: CONTENT_LITERAL_ZONED,
168 claim: "A numeric literal passed BY CONTENT arrives as zoned decimal of its own digits, the sign overpunched when negative",
169 basis: Basis::Chosen,
170 oracle: Oracle::EnterpriseCobol,
171 },
172 Assumption {
173 id: KEYED_FILE_STATUS,
174 claim: "Indexed and relative files report 02 for a shared alternate key, 14 for a record number too long for the RELATIVE KEY on sequential READ, 21 for a sequential WRITE whose key is not above the last (equal included) or a REWRITE that changed the key, 22 duplicate, 23 not found, 24 a record number below 1 or too long for the RELATIVE KEY on WRITE, 43 REWRITE or DELETE with no READ just before, 46 READ NEXT with no next record, and 47, 48, 49 for the wrong open mode",
175 basis: Basis::Recalled,
176 oracle: Oracle::EnterpriseCobol,
177 },
178 Assumption {
179 id: ALTERNATE_KEY_ORDER,
180 claim: "Records sharing an alternate key come back in the order they were written; a record REWRITTEN with a new alternate key goes after the others with it",
181 basis: Basis::Recalled,
182 oracle: Oracle::EnterpriseCobol,
183 },
184 Assumption {
185 id: FAILED_READ_LOSES_POSITION,
186 claim: "A random READ that finds no record leaves no next record, so READ NEXT then gives 46",
187 basis: Basis::Chosen,
188 oracle: Oracle::EnterpriseCobol,
189 },
190 Assumption {
191 id: START_COMPARES_SHORTER,
192 claim: "START compares the key with its operand over the shorter of the two, left to right, as bytes",
193 basis: Basis::Recalled,
194 oracle: Oracle::EnterpriseCobol,
195 },
196 Assumption {
197 id: CICS_FRESH_STORAGE,
198 claim: "A COBOL program reached by EXEC CICS LINK or XCTL starts with fresh WORKING-STORAGE each time, unlike one reached by CALL",
199 basis: Basis::Recalled,
200 oracle: Oracle::EnterpriseCobol,
201 },
202 Assumption {
203 id: CICS_CALEN_RESTORED,
204 claim: "EIBCALEN is the linked program's COMMAREA length while it runs and the caller's again after the LINK returns",
205 basis: Basis::Chosen,
206 oracle: Oracle::EnterpriseCobol,
207 },
208 Assumption {
209 id: CICS_HANDLE_ABEND_CATCHES_CONDITIONS,
210 claim: "HANDLE ABEND LABEL receives control when a condition nothing handles would abend the task (AEIx), and is cancelled by being taken",
211 basis: Basis::Recalled,
212 oracle: Oracle::EnterpriseCobol,
213 },
214 Assumption {
215 id: CICS_LENGTH_DEFAULTS_TO_INTO,
216 claim: "READ, READNEXT, READPREV, READQ TS and READQ TD without LENGTH take the INTO item's length as the limit, so a longer record raises LENGERR",
217 basis: Basis::Recalled,
218 oracle: Oracle::EnterpriseCobol,
219 },
220 Assumption {
221 id: CICS_PROGRAM_CHECK_IS_ASRA,
222 claim: "A program check (S0C4, S0C7 and the like) in a CICS task ends it with transaction abend ASRA",
223 basis: Basis::Recalled,
224 oracle: Oracle::EnterpriseCobol,
225 },
226 Assumption {
227 id: CICS_BROWSE_SKIP,
228 claim: "READNEXT after the program changed RIDFLD to a key the browse is not at continues from the first record at or after the new RIDFLD (skip-sequential)",
229 basis: Basis::Recalled,
230 oracle: Oracle::EnterpriseCobol,
231 },
232 Assumption {
233 id: BMS_RECEIVE_NULLS,
234 claim: "RECEIVE MAP sets the input map to nulls, then fills only the fields the operator modified; a field erased to empty gets F = X'80' and L = 0",
235 basis: Basis::Recalled,
236 oracle: Oracle::EnterpriseCobol,
237 },
238 Assumption {
239 id: BMS_INPUT_JUSTIFY,
240 claim: "Input data lands left-justified and blank-filled unless JUSTIFY says otherwise, and a NUM field right-justified and zero-filled, the defaults IBM documents for JUSTIFY",
241 basis: Basis::Recalled,
242 oracle: Oracle::EnterpriseCobol,
243 },
244 Assumption {
245 id: BMS_EXTENDED_ORDER,
246 claim: "A field's extended attribute bytes in the symbolic map follow its A byte in the order COLOR, PS, HILIGHT, VALIDN, OUTLINE, SOSI, TRANSP",
247 basis: Basis::Chosen,
248 oracle: Oracle::EnterpriseCobol,
249 },
250 Assumption {
251 id: BMS_CONSTANTS_UNVERIFIED,
252 claim: "DFHNULL is X'00', and DFHBMPEM, DFHBMPNL, DFHBMPFF and DFHBMPCR are X'19', X'15', X'0C' and X'0D'",
253 basis: Basis::Recalled,
254 oracle: Oracle::EnterpriseCobol,
255 },
256 Assumption {
257 id: BMS_SEND_DATA_CHOICE,
258 claim: "SEND MAP without MAPONLY or DATAONLY sends a field's symbolic data when its first byte is not X'00', else the map's INITIAL, and a non-null A byte replaces ATTRB",
259 basis: Basis::Recalled,
260 oracle: Oracle::EnterpriseCobol,
261 },
262 Assumption {
263 id: CICS_INITIAL_AID,
264 claim: "A task started by terminal input sees that input's AID in EIBAID before any RECEIVE",
265 basis: Basis::Recalled,
266 oracle: Oracle::EnterpriseCobol,
267 },
268 Assumption {
269 id: REWRITE_SHARED_ALTERNATE,
270 claim: "REWRITE gives 02 whenever another record shares one of the record's alternate keys that allow duplicates, whether or not that key changed",
271 basis: Basis::Chosen,
272 oracle: Oracle::EnterpriseCobol,
273 },
274];
275
276pub fn get(id: &str) -> &'static Assumption {
277 ASSUMPTIONS.iter().find(|a| a.id == id).unwrap_or_else(|| panic!("no assumption {id}"))
278}
279
280#[cfg(test)]
281mod tests {
282 use super::*;
283
284 #[test]
285 fn ids_are_unique() {
286 let mut ids: Vec<_> = ASSUMPTIONS.iter().map(|a| a.id).collect();
287 ids.sort();
288 ids.dedup();
289 assert_eq!(ids.len(), ASSUMPTIONS.len());
290 }
291}