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
//
// GENERATED FILE
//
use super::*;
use crate::SpiceContext;
use f2rust_std::*;
const ISPACE: i32 = 32;
/// Next word in a character string
///
/// Return the next word in a given character string, and
/// left justify the rest of the string.
///
/// # Brief I/O
///
/// ```text
/// VARIABLE I/O DESCRIPTION
/// -------- --- --------------------------------------------------
/// STRING I Input character string.
/// NEXT O The next word in the string.
/// REST O The remaining part of STRING, left-justified.
/// ```
///
/// # Detailed Input
///
/// ```text
/// STRING is the input string to be parsed. Each word of this
/// string is a maximal sequence of consecutive non-blank
/// characters.
/// ```
///
/// # Detailed Output
///
/// ```text
/// NEXT is the first word in STRING. It is called the "next" word
/// because NEXTWD is typically called repeatedly to find the
/// words of the input string in left-to-right order. A word
/// is a maximal sequence of consecutive non-blank
/// characters. NEXT is always returned left-justified.
///
/// If STRING is blank, NEXT is blank.
///
/// NEXT may NOT overwrite STRING.
///
/// REST is the remaining part of STRING, left-justified after the
/// removal of NEXT.
///
/// REST may overwrite STRING.
/// ```
///
/// # Exceptions
///
/// ```text
/// Error free.
///
/// 1) If the declared lengths of NEXT and REST are not large enough
/// to hold the output strings, they are truncated on the right.
/// ```
///
/// # Particulars
///
/// ```text
/// NEXTWD is used primarily for parsing input commands consisting
/// of one or more words, where a word is defined to be any sequence
/// of consecutive non-blank characters. Successive calls to NEXTWD,
/// each using the previous value of REST as the input string, allow
/// the calling routine to neatly parse and process one word at a
/// time.
///
/// NEXTWD cuts the input string into two pieces, and returns them
/// separately. The first piece is the first word in the string.
/// (Leading blanks are ignored. The first word, which is returned in
/// the output argument NEXT, runs from the first non-blank character
/// in the string up to the first blank that follows it.) The second
/// piece is whatever is left after the first word is removed. The
/// second piece is left justified, to simplify later calls to NEXTWD.
/// ```
///
/// # Examples
///
/// ```text
/// The numerical results shown for this example may differ across
/// platforms. The results depend on the SPICE kernels used as
/// input, the compiler and supporting libraries, and the machine
/// specific arithmetic implementation.
///
/// 1) Given a character string, get the sequence of words within.
///
///
/// Example code begins here.
///
///
/// PROGRAM NEXTWD_EX1
/// IMPLICIT NONE
///
/// C
/// C SPICELIB functions.
/// C
/// LOGICAL EQSTR
///
/// C
/// C Local parameters.
/// C
/// INTEGER LINZS
/// PARAMETER ( LINZS = 47 )
///
/// INTEGER WRDSZ
/// PARAMETER ( WRDSZ = 5 )
///
/// C
/// C Local variables.
/// C
/// CHARACTER*(WRDSZ) NEXT
/// CHARACTER*(LINZS) REST
/// CHARACTER*(LINZS) STRING
///
/// REST = ' Now is the time, for all good men to come.'
///
/// WRITE(*,'(A)') 'Next Rest of the string'
/// WRITE(*,'(A)') '----- ---'
/// . // '---------------------------------------'
///
/// DO WHILE ( .NOT. EQSTR ( REST, ' ' ) )
///
/// STRING = REST
/// CALL NEXTWD ( STRING, NEXT, REST )
///
/// WRITE(*,'(A5,2X,A)') NEXT, REST
///
/// END DO
///
/// END
///
///
/// When this program was executed on a Mac/Intel/gfortran/64-bit
/// platform, the output was:
///
///
/// Next Rest of the string
/// ----- ------------------------------------------
/// Now is the time, for all good men to come.
/// is the time, for all good men to come.
/// the time, for all good men to come.
/// time, for all good men to come.
/// for all good men to come.
/// all good men to come.
/// good men to come.
/// men to come.
/// to come.
/// come.
/// ```
///
/// # Author and Institution
///
/// ```text
/// N.J. Bachman (JPL)
/// J. Diaz del Rio (ODC Space)
/// K.R. Gehringer (JPL)
/// W.L. Taber (JPL)
/// I.M. Underwood (JPL)
/// ```
///
/// # Version
///
/// ```text
/// - SPICELIB Version 1.3.0, 19-MAY-2021 (JDR) (NJB)
///
/// Added IMPLICIT NONE statement.
///
/// Edited the header to comply with NAIF standard. Added complete
/// code example based on the existing fragment.
///
/// Updated header documentation. Added entry #1 in $Exceptions
/// section.
///
/// - SPICELIB Version 1.2.0, 04-APR-1996 (KRG)
///
/// Fixed a problem that could occur when STRING and REST are
/// the same character string. Simplified the algorithm a bit
/// while I was at it.
///
/// Single character comparisons now make use of ICHAR to
/// perform the comparisons as integers for speed.
///
/// - SPICELIB Version 1.0.1, 10-MAR-1992 (WLT)
///
/// Comment section for permuted index source lines was added
/// following the header.
///
/// - SPICELIB Version 1.0.0, 31-JAN-1990 (IMU)
/// ```
pub fn nextwd(string: &str, next: &mut str, rest: &mut str) {
NEXTWD(
string.as_bytes(),
fstr::StrBytes::new(next).as_mut(),
fstr::StrBytes::new(rest).as_mut(),
);
}
//$Procedure NEXTWD ( Next word in a character string )
pub fn NEXTWD(STRING: &[u8], NEXT: &mut [u8], REST: &mut [u8]) {
let mut BEGIN: i32 = 0;
let mut END: i32 = 0;
let mut I: i32 = 0;
let mut INWORD: bool = false;
//
// Local Parameters
//
//
// Local variables
//
//
// The trivial case.
//
if fstr::eq(STRING, b" ") {
fstr::assign(NEXT, b" ");
fstr::assign(REST, b" ");
//
// The non-trivial case.
//
} else {
//
// Get the length of the string.
//
END = intrinsics::LEN(STRING);
//
// Skip leading blanks and set flags indicating that we are
// not in a word and that we do not have a word.
//
BEGIN = 1;
INWORD = false;
//
// We know the string is not blank, so we will eventually
// get to a word, thus no need to check against END here.
//
while !INWORD {
if (intrinsics::ICHAR(fstr::substr(STRING, BEGIN..=BEGIN)) == ISPACE) {
BEGIN = (BEGIN + 1);
} else {
INWORD = true;
}
}
//
// We are now in a word. Step through the input string until the
// next blank is encountered or until the end of the string is
// found. We start at BEGIN even though we know from above that
// STRING(BEGIN:BEGIN) is not blank; this allows us to deal
// cleanly with the case where the string is a single character
// long and not blank (because we're in that case).
//
I = BEGIN;
while INWORD {
if (intrinsics::ICHAR(fstr::substr(STRING, I..=I)) != ISPACE) {
I = (I + 1);
if (I > END) {
I = (I - 1);
INWORD = false;
}
} else {
I = (I - 1);
INWORD = false;
}
}
//
// Our word is the substring between BEGIN and I. Note that I
// might be equal to END, so we have to be careful about setting
// the REST. We also left justify REST as we set it. LJUST does
// the right thing if STRING and REST overlap. If we do not have
// a word, the NEXT and REST are both blank.
//
fstr::assign(NEXT, fstr::substr(STRING, BEGIN..=I));
if (I < END) {
LJUST(fstr::substr(STRING, (I + 1)..), REST);
} else {
fstr::assign(REST, b" ");
}
}
}