1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
//
// GENERATED FILE
//
use super::*;
use f2rust_std::*;
const LNGLEN: i32 = 128;
const MIDLEN: i32 = (LNGLEN / 2);
const RECLEN: i32 = (LNGLEN / 2);
const NFILES: i32 = 12;
const EOLTSZ: i32 = 5;
//$Procedure F_ZZASC2 ( Family of tests for ZZASCII )
pub fn F_ZZASC2(OK: &mut bool, ctx: &mut Context) -> f2rust_std::Result<()> {
let mut IOSTAT: i32 = 0;
let mut NUMBER: i32 = 0;
let mut LINE = ActualCharArray::new(MIDLEN, 1..=3);
let mut TERMIN = ActualCharArray::new(2, 1..=3);
let mut HLINE = [b' '; MIDLEN as usize];
let mut FILES = ActualCharArray::new(12, 1..=NFILES);
let mut MYFILE = [b' '; 12 as usize];
let mut OUTTRM = [b' '; EOLTSZ as usize];
let mut WRKLIN = [b' '; LNGLEN as usize];
let mut XSHRTL = [b' '; 2 as usize];
let mut MYZZEF = StackArray::<bool, 12>::new(1..=NFILES);
let mut MYZZEM = ActualCharArray::new(32, 1..=NFILES);
let mut MYTERM = ActualCharArray::new(EOLTSZ, 1..=NFILES);
let mut MYFNEF = StackArray::<bool, 12>::new(1..=NFILES);
let mut MYFNEM = ActualCharArray::new(32, 1..=NFILES);
//
// Local parameters
//
//
// Local Variables.
//
//
// SPICELIB functions.
//
//
// Open the test family.
//
testutil::TOPEN(b"F_ZZASC2", ctx)?;
//
// Define the data to write to test files. ID the file as an LSK
// kernel, with a begin text block - thus we don't risk damaging any
// kernel pool variable assignments. The third line contains the
// data to write.
//
fstr::assign(
LINE.get_mut(1),
b"KPL/LSK ",
);
fstr::assign(
LINE.get_mut(2),
b"\\begintext ",
);
fstr::assign(
LINE.get_mut(3),
b"1234567890123456789012345678901234567890123456789012345678901234",
);
//
// Initialize the file names. The first three files will be smaller
// than the buffer that will be used to read them. The second three
// will have exactly same size as the buffer. The third three will
// be larger than the buffer. The last three will be larger than the
// buffer but will contain mixed terminators.
//
fstr::assign(FILES.get_mut(1), b"macs.ker");
fstr::assign(FILES.get_mut(2), b"unxs.ker");
fstr::assign(FILES.get_mut(3), b"doss.ker");
fstr::assign(FILES.get_mut(4), b"macm.ker");
fstr::assign(FILES.get_mut(5), b"unxm.ker");
fstr::assign(FILES.get_mut(6), b"dosm.ker");
fstr::assign(FILES.get_mut(7), b"macl.ker");
fstr::assign(FILES.get_mut(8), b"unxl.ker");
fstr::assign(FILES.get_mut(9), b"dosl.ker");
fstr::assign(FILES.get_mut(10), b"mxd1.ker");
fstr::assign(FILES.get_mut(11), b"mxd2.ker");
fstr::assign(FILES.get_mut(12), b"mxd3.ker");
//
// Initialize terminators and tags.
//
fstr::assign(
TERMIN.get_mut(1),
&fstr::concat(&intrinsics::CHAR(13), b" "),
);
fstr::assign(
TERMIN.get_mut(2),
&fstr::concat(&intrinsics::CHAR(10), b" "),
);
fstr::assign(
TERMIN.get_mut(3),
&fstr::concat(&intrinsics::CHAR(13), &intrinsics::CHAR(10)),
);
//
// Generate test files. The first loop ("I" loop) controls how many
// records will be written to the test files (up to three, the 4th
// is for the mixed files.)
//
for I in 1..=4 {
//
// The second loop ("J" loop) goes over triplets of files and
// corresponding terminators.
//
for J in 1..=3 {
//
// If the test file exists, delete it.
//
fstr::assign(&mut MYFILE, FILES.get((((I - 1) * 3) + J)));
if spicelib::EXISTS(&MYFILE, ctx)? {
testutil::KILFIL(&MYFILE, ctx)?;
}
//
// Find a free logical unit and open the file as direct access.
//
spicelib::GETLUN(&mut NUMBER, ctx)?;
{
use f2rust_std::io;
let specs = io::OpenSpecs {
unit: Some(NUMBER),
file: Some(&MYFILE),
access: Some(b"DIRECT"),
status: Some(b"NEW"),
recl: Some(RECLEN),
..Default::default()
};
IOSTAT = io::capture_iostat(|| ctx.open(specs))?;
}
//
// The third loop ("REC" loop) pads "I" lines with the right
// terminators (for the first three file triplets) or with
// mixed terminators (for the last triplet) and writes them to
// the file.
//
for REC in 1..=I {
//
// Copy line to temporary buffer, add the terminator and
// write it to the file. If REC is 4 or greater, use
// incorrect terminator to get all flavors of
// "contaminated" files.
//
if (REC <= 3) {
fstr::assign(&mut HLINE, LINE.get(REC));
fstr::assign(
fstr::substr_mut(&mut HLINE, (MIDLEN - 1)..=MIDLEN),
TERMIN.get(J),
);
{
use f2rust_std::{
data::Val,
io::{self, Writer},
};
let mut writer =
io::UnformattedWriter::new(ctx.io_unit(NUMBER)?, Some(REC))?;
writer.start()?;
writer.write_str(fstr::substr(&HLINE, 1..=MIDLEN))?;
writer.finish()?;
}
} else {
fstr::assign(&mut HLINE, LINE.get(1));
if (J == 1) {
fstr::assign(
fstr::substr_mut(&mut HLINE, (MIDLEN - 1)..=MIDLEN),
TERMIN.get(2),
);
} else if (J == 2) {
fstr::assign(
fstr::substr_mut(&mut HLINE, (MIDLEN - 1)..=MIDLEN),
TERMIN.get(3),
);
} else if (J == 3) {
fstr::assign(
fstr::substr_mut(&mut HLINE, (MIDLEN - 1)..=MIDLEN),
TERMIN.get(1),
);
}
{
use f2rust_std::{
data::Val,
io::{self, Writer},
};
let mut writer = io::UnformattedWriter::new(ctx.io_unit(NUMBER)?, Some(1))?;
writer.start()?;
writer.write_str(fstr::substr(&HLINE, 1..=MIDLEN))?;
writer.finish()?;
}
}
}
//
// Close the file.
//
{
use f2rust_std::io;
let specs = io::CloseSpecs {
unit: Some(NUMBER),
..Default::default()
};
ctx.close(specs)?;
}
}
}
//
// Ensure ZZASCII signals an error for work line lengths below the 3
// character threshold.
//
testutil::TCASE(b"Check for error when using tiny buffer.", ctx)?;
spicelib::ZZASCII(&FILES[1], &mut XSHRTL, false, &mut OUTTRM, ctx)?;
testutil::CHCKXC(true, b"SPICE(STRINGTOOSHORT)", OK, ctx)?;
//
// Ensure ZZASCII signals an error for a file that cannot be opened.
//
testutil::TCASE(b"Check for error when cannot open the file.", ctx)?;
spicelib::ZZASCII(b"hakuna-matata", &mut WRKLIN, false, &mut OUTTRM, ctx)?;
testutil::CHCKXC(true, b"SPICE(FILEOPENFAIL)", OK, ctx)?;
//
// Set ZZASCII exception flag and exception message for each file.
// Since all files exist and buffer is big enough there should not
// be any exceptions on any of the platforms.
//
for I in 1..=NFILES {
MYZZEF[I] = false;
fstr::assign(MYZZEM.get_mut(I), b" ");
}
//
// Set ZZASCII output terminator for each file. These are a
// different story. We assign them as they should be detected
// everywhere, but reassign some/all for the platforms that don't
// "behave."
//
fstr::assign(MYTERM.get_mut(1), b"?");
fstr::assign(MYTERM.get_mut(2), b"?");
fstr::assign(MYTERM.get_mut(3), b"?");
fstr::assign(MYTERM.get_mut(4), b"CR");
fstr::assign(MYTERM.get_mut(5), b"LF");
fstr::assign(MYTERM.get_mut(6), b"CR-LF");
fstr::assign(MYTERM.get_mut(7), b"CR");
fstr::assign(MYTERM.get_mut(8), b"LF");
fstr::assign(MYTERM.get_mut(9), b"CR-LF");
fstr::assign(MYTERM.get_mut(10), b"?");
fstr::assign(MYTERM.get_mut(11), b"?");
fstr::assign(MYTERM.get_mut(12), b"?");
//
// The IFORT, GFORTRAN, DIGITAL, and LAHEY seem to
// generate IOSTAT=0 when read past the end of a file and,
// therefore, proceed and detect terminators in short files.
//
fstr::assign(MYTERM.get_mut(1), b"CR");
fstr::assign(MYTERM.get_mut(2), b"LF");
fstr::assign(MYTERM.get_mut(3), b"CR-LF");
//
// Set FURNSH exception flag, exception message and loaded flag for
// each file as if FURNSH wouldn't fail and then reset some of them
// depending on the platform.
//
for I in 1..=NFILES {
MYFNEF[I] = false;
fstr::assign(MYFNEM.get_mut(I), b" ");
}
//
// IFORT on Macs and Linux and GFORTRAN everywhere can detect
// terminators in small and medium files and, therefore, complain
// about them same way as for the large files.
//
MYFNEF[1] = true;
MYFNEF[3] = true;
MYFNEF[4] = true;
MYFNEF[6] = true;
MYFNEF[7] = true;
MYFNEF[9] = true;
fstr::assign(MYFNEM.get_mut(1), b"SPICE(INCOMPATIBLEEOL)");
fstr::assign(MYFNEM.get_mut(3), b"SPICE(INCOMPATIBLEEOL)");
fstr::assign(MYFNEM.get_mut(4), b"SPICE(INCOMPATIBLEEOL)");
fstr::assign(MYFNEM.get_mut(6), b"SPICE(INCOMPATIBLEEOL)");
fstr::assign(MYFNEM.get_mut(7), b"SPICE(INCOMPATIBLEEOL)");
fstr::assign(MYFNEM.get_mut(9), b"SPICE(INCOMPATIBLEEOL)");
//
// Now go over the files and call ZZASCII and FURNSH on each of them.
//
for I in 1..=NFILES {
//
// Direct check by calling ZZASCII.
//
testutil::TCASE(
&fstr::concat(b"Check for EOL terminator in ", FILES.get(I)),
ctx,
)?;
spicelib::ZZASCII(&FILES[I], &mut WRKLIN, false, &mut OUTTRM, ctx)?;
testutil::CHCKXC(MYZZEF[I], &MYZZEM[I], OK, ctx)?;
testutil::CHCKSC(b"Terminator", &OUTTRM, b"=", &MYTERM[I], OK, ctx)?;
//
// Indirect check by calling FURNSH.
//
testutil::TCASE(
&fstr::concat(b"Check what FURNSH does with ", FILES.get(I)),
ctx,
)?;
spicelib::FURNSH(&FILES[I], ctx)?;
testutil::CHCKXC(MYFNEF[I], &MYFNEM[I], OK, ctx)?;
if !MYFNEF[I] {
spicelib::UNLOAD(&FILES[I], ctx)?;
}
}
//
// Clean-up: delete test files.
//
for I in 1..=12 {
testutil::KILFIL(&FILES[I], ctx)?;
}
//
// Close out the test family.
//
testutil::T_SUCCESS(OK, ctx);
Ok(())
}