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
//
// GENERATED FILE
//
use super::*;
use f2rust_std::*;
const MOSTDG: i32 = 33;
const FMTPIC: &[u8] = b"(1PE#.#)";
struct SaveVars {
MAXSAV: i32,
FMTSTR: Vec<u8>,
FIRST: bool,
}
impl SaveInit for SaveVars {
fn new() -> Self {
let mut MAXSAV: i32 = 0;
let mut FMTSTR = vec![b' '; 10 as usize];
let mut FIRST: bool = false;
FIRST = true;
MAXSAV = 14;
fstr::assign(&mut FMTSTR, b"(1PE20.13)");
Self {
MAXSAV,
FMTSTR,
FIRST,
}
}
}
//$Procedure DPSTRE ( Double Precision Number to Character )
pub fn DPSTRE(X: f64, SIGDIG: i32, STRING: &mut [u8], ctx: &mut Context) -> f2rust_std::Result<()> {
let save = ctx.get_vars::<SaveVars>();
let save = &mut *save.borrow_mut();
let mut IOSTAT: i32 = 0;
let mut MAXSIG: i32 = 0;
let mut NUMSTR = [b' '; (MOSTDG + 7) as usize];
//
// Local parameters.
//
// The maximum number of allowed significant digits is set to 33
// (=16*2+1). This is an arbitrarily picked value because FORTRAN
// doesn't seen to have a limit. But we do need a limit to make sure
// that the formatted WRITE does not overflow the local buffer
// string.
//
//
//
// Format template.
//
//
// Local variables
//
//
// Saved variables.
//
//
// Initial values.
//
//
// Reset the input number of significant digits if it is outside of
// the allowed range (1 to 33).
//
MAXSIG = intrinsics::MIN0(&[MOSTDG, intrinsics::MAX0(&[1, SIGDIG])]);
//
// If the number of significant digits is less then or equal to 14,
// outsource conversion to DPSTR.
//
if (MAXSIG <= 14) {
spicelib::DPSTR(X, MAXSIG, STRING, ctx);
} else {
//
// The number of significant digits is greater than 14. Make
// output format. Do it only for the first call or if the
// previous call had a different number of significant digits.
// Otherwise, use the SAVEd format string from the previous
// call.
//
if (save.FIRST || (MAXSIG != save.MAXSAV)) {
fstr::assign(&mut save.FMTSTR, FMTPIC);
spicelib::REPMI(
&save.FMTSTR.to_vec(),
b"#",
(MAXSIG + 6),
&mut save.FMTSTR,
ctx,
);
spicelib::REPMI(
&save.FMTSTR.to_vec(),
b"#",
(MAXSIG - 1),
&mut save.FMTSTR,
ctx,
);
save.MAXSAV = MAXSIG;
save.FIRST = false;
}
//
// Use WRITE to create a temporary output string. This string is
// declared to have enough room for any allowed numbers of
// significant digits. We should not get any errors.
//
{
use f2rust_std::{
data::Val,
io::{self, Writer},
};
let internal_file = io::InternalFile::open(&mut NUMSTR);
let mut writer = io::FormattedWriter::new(internal_file, None, &save.FMTSTR)?;
IOSTAT = io::capture_iostat(|| {
writer.start()?;
writer.write_f64(X)?;
writer.finish()?;
Ok(())
})?;
}
//
// This is fail safe check. Since we made the format string
// ourselves and declared the output string with enough room we
// should never hit it. But we do this check anyway, just in
// case.
//
if (IOSTAT != 0) {
spicelib::CHKIN(b"DPSTRE", ctx)?;
spicelib::SETMSG(
b"Bug. FORTRAN WRITE failed; number = #; format = #; IOSTAT = #",
ctx,
);
spicelib::ERRDP(b"#", X, ctx);
spicelib::ERRCH(b"#", &save.FMTSTR, ctx);
spicelib::ERRINT(b"#", IOSTAT, ctx);
spicelib::SIGERR(b"SPICE(BUGWRITEFAILED)", ctx)?;
spicelib::CHKOUT(b"DPSTRE", ctx)?;
return Ok(());
}
//
// NOTE 1: should we also check for '*'s?
//
// NOTE 2: should we check for 'E' in the string for cases of
// output FORTRAN WRITE for numbers greater than 1D100?
// (In this case GFORTRAN leaves E out and prints
// pi*1D101 like this -3.14+101.)
//
//
// Assign output string.
//
fstr::assign(STRING, &NUMSTR);
}
Ok(())
}