1 | #include "slalib.h"
|
---|
2 | #include "slamac.h"
|
---|
3 | #include <string.h>
|
---|
4 | #include <limits.h>
|
---|
5 |
|
---|
6 | static int idchi ( int, char*, int*, double* );
|
---|
7 |
|
---|
8 | void slaIntin ( char *string, int *nstrt, long *ireslt, int *jflag )
|
---|
9 | /*
|
---|
10 | ** - - - - - - - - -
|
---|
11 | ** s l a I n t i n
|
---|
12 | ** - - - - - - - - -
|
---|
13 | **
|
---|
14 | ** Convert free-format input into a long integer.
|
---|
15 | **
|
---|
16 | ** Given:
|
---|
17 | ** string char* string containing number to be decoded
|
---|
18 | ** nstrt int* where to start decode (1st = 1)
|
---|
19 | ** ireslt long* current value of result
|
---|
20 | **
|
---|
21 | ** Returned:
|
---|
22 | ** nstrt int* advanced to next number
|
---|
23 | ** ireslt long* result
|
---|
24 | ** jflag int* status: -1 = -OK, 0 = +OK, 1 = null, 2 = error
|
---|
25 | **
|
---|
26 | ** Called: idchi
|
---|
27 | **
|
---|
28 | ** Notes:
|
---|
29 | **
|
---|
30 | ** 1 The reason slaIntin has separate OK status values for +
|
---|
31 | ** and - is to enable minus zero to be detected. This is
|
---|
32 | ** of crucial importance when decoding mixed-radix numbers.
|
---|
33 | ** For example, an angle expressed as deg, arcmin, arcsec
|
---|
34 | ** may have a leading minus sign but a zero degrees field.
|
---|
35 | **
|
---|
36 | ** 2 A TAB is interpreted as a space.
|
---|
37 | **
|
---|
38 | ** 3 The basic format is the sequence of fields #^, where
|
---|
39 | ** # is a sign character + or -, and ^ means a string of
|
---|
40 | ** decimal digits.
|
---|
41 | **
|
---|
42 | ** 4 Spaces:
|
---|
43 | **
|
---|
44 | ** . Leading spaces are ignored.
|
---|
45 | **
|
---|
46 | ** . Spaces between the sign and the number are allowed.
|
---|
47 | **
|
---|
48 | ** . Trailing spaces are ignored; the first signifies
|
---|
49 | ** end of decoding and subsequent ones are skipped.
|
---|
50 | **
|
---|
51 | ** 5 Delimiters:
|
---|
52 | **
|
---|
53 | ** . Any character other than +,-,0-9 or space may be
|
---|
54 | ** used to signal the end of the number and terminate
|
---|
55 | ** decoding.
|
---|
56 | **
|
---|
57 | ** . Comma is recognized by slaIntin as a special case; it
|
---|
58 | ** is skipped, leaving the pointer on the next character.
|
---|
59 | ** See 9, below.
|
---|
60 | **
|
---|
61 | ** 6 The sign is optional. The default is +.
|
---|
62 | **
|
---|
63 | ** 7 A "null result" occurs when the string of characters being
|
---|
64 | ** decoded does not begin with +,- or 0-9, or consists
|
---|
65 | ** entirely of spaces. When this condition is detected, jflag
|
---|
66 | ** is set to 1 and ireslt is left untouched.
|
---|
67 | **
|
---|
68 | ** 8 nstrt = 1 for the first character in the string.
|
---|
69 | **
|
---|
70 | ** 9 On return from slaIntin, nstrt is set ready for the next
|
---|
71 | ** decode - following trailing blanks and any comma. If a
|
---|
72 | ** delimiter other than comma is being used, nstrt must be
|
---|
73 | ** incremented before the next call to slaIntin, otherwise
|
---|
74 | ** all subsequent calls will return a null result.
|
---|
75 | **
|
---|
76 | ** 10 Errors (jflag=2) occur when:
|
---|
77 | **
|
---|
78 | ** . there is a + or - but no number; or
|
---|
79 | **
|
---|
80 | ** . the number is larger than LONG_MAX.
|
---|
81 | **
|
---|
82 | ** 11 When an error has been detected, nstrt is left
|
---|
83 | ** pointing to the character following the last
|
---|
84 | ** one used before the error came to light.
|
---|
85 | **
|
---|
86 | ** 12 See also slaFlotin and slaDfltin.
|
---|
87 | **
|
---|
88 | ** Last revision: 6 November 1999
|
---|
89 | **
|
---|
90 | ** Copyright P.T.Wallace. All rights reserved.
|
---|
91 | */
|
---|
92 |
|
---|
93 | /* Definitions shared between slaIntin and idchi */
|
---|
94 | #define NUMBER 0
|
---|
95 | #define SPACE 1
|
---|
96 | #define PLUS 2
|
---|
97 | #define MINUS 3
|
---|
98 | #define COMMA 4
|
---|
99 | #define OTHER 5
|
---|
100 | #define END 6
|
---|
101 |
|
---|
102 | {
|
---|
103 | int l_string, nptr;
|
---|
104 | double digit;
|
---|
105 |
|
---|
106 | /* Current state of the decode and the values it can take */
|
---|
107 |
|
---|
108 | int state;
|
---|
109 |
|
---|
110 | #define seek_sign 100
|
---|
111 | #define neg 200
|
---|
112 | #define seek_1st_digit 300
|
---|
113 | #define accept_digit 400
|
---|
114 | #define seek_digit 410
|
---|
115 | #define end_of_field 1600
|
---|
116 | #define build_result 1610
|
---|
117 | #define seeking_end_of_field 1630
|
---|
118 | #define next_field_OK 1720
|
---|
119 | #define next_field_default 9100
|
---|
120 | #define null_field 9110
|
---|
121 | #define next_field_error 9200
|
---|
122 | #define error 9210
|
---|
123 | #define done 9900
|
---|
124 |
|
---|
125 |
|
---|
126 | int j;
|
---|
127 | double dres;
|
---|
128 |
|
---|
129 |
|
---|
130 | /* Find string length */
|
---|
131 | l_string = strlen ( string );
|
---|
132 |
|
---|
133 | /* Current character index (1st = 0) */
|
---|
134 | nptr = *nstrt - 1;
|
---|
135 |
|
---|
136 | /* Set defaults: result & sign */
|
---|
137 | dres = 0.0;
|
---|
138 | j = 0;
|
---|
139 |
|
---|
140 | /* Initialize state to "looking for sign" */
|
---|
141 | state = seek_sign;
|
---|
142 |
|
---|
143 | /* Loop until decode is complete */
|
---|
144 | while ( state != done ) {
|
---|
145 | switch ( state ) {
|
---|
146 |
|
---|
147 | case seek_sign :
|
---|
148 |
|
---|
149 | /* Look for sign */
|
---|
150 | switch ( idchi ( l_string, string, &nptr, &digit ) ) {
|
---|
151 | case NUMBER :
|
---|
152 | state = accept_digit;
|
---|
153 | break;
|
---|
154 | case SPACE :
|
---|
155 | state = seek_sign;
|
---|
156 | break;
|
---|
157 | case PLUS :
|
---|
158 | state = seek_1st_digit;
|
---|
159 | break;
|
---|
160 | case MINUS :
|
---|
161 | state = neg;
|
---|
162 | break;
|
---|
163 | case OTHER :
|
---|
164 | state = next_field_default;
|
---|
165 | break;
|
---|
166 | case COMMA :
|
---|
167 | case END :
|
---|
168 | state = null_field;
|
---|
169 | break;
|
---|
170 | default :
|
---|
171 | state = error;
|
---|
172 | }
|
---|
173 | break;
|
---|
174 |
|
---|
175 | case neg :
|
---|
176 |
|
---|
177 | /* Negative result */
|
---|
178 | j = -1;
|
---|
179 |
|
---|
180 | case seek_1st_digit :
|
---|
181 |
|
---|
182 | /* Look for first leading decimal */
|
---|
183 | switch ( idchi ( l_string, string, &nptr, &digit ) ) {
|
---|
184 | case NUMBER :
|
---|
185 | state = accept_digit;
|
---|
186 | break;
|
---|
187 | case SPACE :
|
---|
188 | state = seek_1st_digit;
|
---|
189 | break;
|
---|
190 | case PLUS :
|
---|
191 | case MINUS :
|
---|
192 | case COMMA :
|
---|
193 | case OTHER :
|
---|
194 | state = next_field_error;
|
---|
195 | break;
|
---|
196 | case END :
|
---|
197 | default :
|
---|
198 | state = error;
|
---|
199 | }
|
---|
200 | break;
|
---|
201 |
|
---|
202 | case accept_digit :
|
---|
203 |
|
---|
204 | /* Accept decimals */
|
---|
205 | dres = dres * 1e1 + digit;
|
---|
206 | state = ( fabs ( dres ) <= LONG_MAX) ?
|
---|
207 | seek_digit : next_field_error;
|
---|
208 | break;
|
---|
209 |
|
---|
210 | case seek_digit :
|
---|
211 |
|
---|
212 | /* Look for next decimal */
|
---|
213 | switch ( idchi ( l_string, string, &nptr, &digit ) ) {
|
---|
214 | case NUMBER :
|
---|
215 | state = accept_digit;
|
---|
216 | break;
|
---|
217 | case SPACE :
|
---|
218 | state = build_result;
|
---|
219 | break;
|
---|
220 | case PLUS :
|
---|
221 | case MINUS :
|
---|
222 | case COMMA :
|
---|
223 | case OTHER :
|
---|
224 | state = end_of_field;
|
---|
225 | break;
|
---|
226 | case END :
|
---|
227 | state = build_result;
|
---|
228 | break;
|
---|
229 | default :
|
---|
230 | state = error;
|
---|
231 | }
|
---|
232 | break;
|
---|
233 |
|
---|
234 | case end_of_field :
|
---|
235 |
|
---|
236 | /* Off the end of the field: move pointer back */
|
---|
237 | nptr--;
|
---|
238 |
|
---|
239 | case build_result :
|
---|
240 |
|
---|
241 | /* Make the result */
|
---|
242 | if ( j ) dres = - dres;
|
---|
243 | *ireslt = (long) ( dnint ( dres ) );
|
---|
244 |
|
---|
245 | case seeking_end_of_field :
|
---|
246 |
|
---|
247 | /* Skip to end of field */
|
---|
248 | switch ( idchi ( l_string, string, &nptr, &digit ) ) {
|
---|
249 | case SPACE :
|
---|
250 | state = seeking_end_of_field;
|
---|
251 | break;
|
---|
252 | case NUMBER :
|
---|
253 | case PLUS :
|
---|
254 | case MINUS :
|
---|
255 | case OTHER :
|
---|
256 | state = next_field_OK;
|
---|
257 | break;
|
---|
258 | case COMMA :
|
---|
259 | case END :
|
---|
260 | state = done;
|
---|
261 | break;
|
---|
262 | default :
|
---|
263 | state = error;
|
---|
264 | }
|
---|
265 | break;
|
---|
266 |
|
---|
267 | case next_field_OK :
|
---|
268 |
|
---|
269 | /* Next field terminates successful decode */
|
---|
270 | nptr--;
|
---|
271 | state = done;
|
---|
272 | break;
|
---|
273 |
|
---|
274 | case next_field_default :
|
---|
275 |
|
---|
276 | /* Next field terminates null decode */
|
---|
277 | nptr--;
|
---|
278 |
|
---|
279 | case null_field :
|
---|
280 |
|
---|
281 | /* Null decode */
|
---|
282 | j = 1;
|
---|
283 | state = done;
|
---|
284 | break;
|
---|
285 |
|
---|
286 | case next_field_error :
|
---|
287 |
|
---|
288 | /* Next field detected prematurely */
|
---|
289 | nptr--;
|
---|
290 |
|
---|
291 | case error :
|
---|
292 |
|
---|
293 | /* Decode has failed: set bad status */
|
---|
294 | j = 2;
|
---|
295 | state = done;
|
---|
296 | break;
|
---|
297 |
|
---|
298 | default :
|
---|
299 | state = error;
|
---|
300 | }
|
---|
301 | }
|
---|
302 |
|
---|
303 | /* Finished: return updated pointer and the status */
|
---|
304 | *nstrt = nptr + 1;
|
---|
305 | *jflag = j;
|
---|
306 | }
|
---|
307 |
|
---|
308 | static int idchi ( int l_string, char *string, int *nptr, double *digit )
|
---|
309 | /*
|
---|
310 | ** - - - - -
|
---|
311 | ** i d c h i
|
---|
312 | ** - - - - -
|
---|
313 | **
|
---|
314 | ** Internal routine used by slaIntin:
|
---|
315 | **
|
---|
316 | ** identify next character in string.
|
---|
317 | **
|
---|
318 | ** Given:
|
---|
319 | ** l_string int length of string
|
---|
320 | ** string char* string
|
---|
321 | ** nptr int* character to be identified (1st = 0)
|
---|
322 | **
|
---|
323 | ** Returned:
|
---|
324 | ** nptr int* incremented unless end of field
|
---|
325 | ** digit double* 0.0 - 9.0 if character was a numeral
|
---|
326 | **
|
---|
327 | ** Returned (function value):
|
---|
328 | ** int vector for identified character:
|
---|
329 | **
|
---|
330 | ** value meaning
|
---|
331 | **
|
---|
332 | ** NUMBER 0-9
|
---|
333 | ** SPACE space or tab
|
---|
334 | ** PLUS +
|
---|
335 | ** MINUS -
|
---|
336 | ** COMMA ,
|
---|
337 | ** OTHER else
|
---|
338 | ** END outside field
|
---|
339 | **
|
---|
340 | ** Last revision: 24 June 1996
|
---|
341 | **
|
---|
342 | ** Copyright P.T.Wallace. All rights reserved.
|
---|
343 | */
|
---|
344 | {
|
---|
345 | int ivec, ictab;
|
---|
346 | char c;
|
---|
347 |
|
---|
348 | /* Character/vector tables */
|
---|
349 |
|
---|
350 | #define NCREC (15)
|
---|
351 | static char kctab[NCREC] = { '0','1','2','3','4','5',
|
---|
352 | '6','7','8','9',
|
---|
353 | ' ','\t',
|
---|
354 | '+',
|
---|
355 | '-',
|
---|
356 | ',' };
|
---|
357 |
|
---|
358 | static int kvtab[NCREC] = { NUMBER, NUMBER, NUMBER, NUMBER, NUMBER,
|
---|
359 | NUMBER, NUMBER, NUMBER, NUMBER, NUMBER,
|
---|
360 | SPACE, SPACE,
|
---|
361 | PLUS,
|
---|
362 | MINUS,
|
---|
363 | COMMA };
|
---|
364 |
|
---|
365 |
|
---|
366 | /* Initialize returned value */
|
---|
367 | ivec = OTHER;
|
---|
368 |
|
---|
369 | /* Pointer outside field? */
|
---|
370 | if ( *nptr < 0 || *nptr >= l_string ) {
|
---|
371 |
|
---|
372 | /* Yes: prepare returned value */
|
---|
373 | ivec = END;
|
---|
374 |
|
---|
375 | } else {
|
---|
376 |
|
---|
377 | /* Not end of field: identify character */
|
---|
378 | c = string [ *nptr ];
|
---|
379 | for ( ictab = 0; ictab < NCREC; ictab++ ) {
|
---|
380 | if ( kctab [ ictab ] == c ) {
|
---|
381 |
|
---|
382 | /* Recognized */
|
---|
383 | ivec = kvtab [ ictab ];
|
---|
384 |
|
---|
385 | /* Allow for numerals */
|
---|
386 | *digit = (double) ictab;
|
---|
387 |
|
---|
388 | /* Quit the loop */
|
---|
389 | break;
|
---|
390 | }
|
---|
391 | }
|
---|
392 |
|
---|
393 | /* Increment pointer */
|
---|
394 | ( *nptr )++;
|
---|
395 | }
|
---|
396 |
|
---|
397 | /* Return the value identifying the character */
|
---|
398 | return ivec;
|
---|
399 | }
|
---|