source: trunk/MagicSoft/slalib/intin.c@ 9492

Last change on this file since 9492 was 731, checked in by tbretz, 24 years ago
*** empty log message ***
  • Property svn:executable set to *
File size: 10.1 KB
Line 
1#include "slalib.h"
2#include "slamac.h"
3#include <string.h>
4#include <limits.h>
5
6static int idchi ( int, char*, int*, double* );
7
8void 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
308static 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}
Note: See TracBrowser for help on using the repository browser.