File: palIntin.c

package info (click to toggle)
starlink-pal 0.9.8-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 1,808 kB
  • sloc: ansic: 6,689; makefile: 128; sh: 81
file content (185 lines) | stat: -rw-r--r-- 5,368 bytes parent folder | download
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
/*
*+
*  Name:
*     palIntin

*  Purpose:
*     Convert free-format input into an integer

*  Language:
*     Starlink ANSI C

*  Type of Module:
*     Library routine

*  Invocation:
*     void palIntin( const char * string, int *nstrt,
*                     long *ireslt, int *jflag );

*  Arguments:
*     string = const char * (Given)
*        String containing number to be decoded.
*     nstrt = int * (Given and Returned)
*        Character number indicating where decoding should start.
*        On output its value is updated to be the location of the
*        possible next value. For compatibility with SLA the first
*        character is index 1.
*     ireslt = long * (Returned)
*        Result. Not updated when jflag=1.
*     jflag = int * (Returned)
*        status: -1 = -OK, 0 = +OK, 1 = null, 2 = error

*  Description:
*     Extracts a number from an input string starting at the specified
*     index.

*  Authors:
*     TIMJ: Tim Jenness (JAC, Hawaii)
*     {enter_new_authors_here}

*  Notes:
*     - Uses the strtol() system call to do the parsing. This may lead to
*       subtle differences when compared to the SLA/F parsing.
*     - Commas are recognized as a special case and are skipped if one happens
*       to be the next character when updating nstrt. Additionally the output
*       nstrt position will skip past any trailing space.
*     - If no number can be found flag will be set to 1.
*     - If the number overflows or underflows jflag will be set to 2. For overflow
*       the returned result will have the value LONG_MAX, for underflow it
*       will have the value LONG_MIN.

*  History:
*     2012-03-15 (TIMJ):
*        Initial version
*        Matches the SLALIB interface but brand new implementation using
*        C library calls and not a direct port of the Fortran.
*     2014-08-07 (TIMJ):
*        Check for isblank availability.
*     {enter_further_changes_here}

*  Copyright:
*     Copyright (C) 2012,2014 Science and Technology Facilities Council.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 3 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
*     MA 02110-1301, USA.

*  Bugs:
*     {note_any_bugs_here}
*-
*/

#if HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdlib.h>
#include <errno.h>

/* isblank() is a C99 feature so we just reimplement it if it is missing */
#if HAVE_ISBLANK
#ifndef _ISOC99_SOURCE
#define _ISOC99_SOURCE
#endif
#include <ctype.h>
# define ISBLANK isblank
#else

static int ISBLANK( int c ) {
  return ( c == ' ' || c == '\t' );
}

#endif

/* Still need ctype for isalpha and isdigit */
#include <ctype.h>

#include "pal.h"

void palIntin( const char * string, int *nstrt,
               long *ireslt, int *jflag ) {

  const char *strstart = NULL; /* Pointer to start of search */
  const char * ctemp = NULL; /* Pointer into string */
  char * endptr = NULL;/* Pointer to string after number */
  int retval;       /* Return value from strtol */
  int hasminus;     /* is this a -0 */

  /* strtol man page indicates that we should reset errno before
     calling strtod */
  errno = 0;

  /* Locate the start postion */
  strstart = &(string[*nstrt-1]);

  /* We have to be able to deal with -0 so we have to search the
     string first and look for the negative */
  hasminus = 0;
  ctemp = strstart;
  while ( ctemp != '\0' ) {
    if (isdigit(*ctemp)) break;
    /* Reset so that - 12345 is not a negative number */
    hasminus = 0;
    /* Flag that we have found a minus */
    if (*ctemp == '-') hasminus = 1;
    ctemp++;
  }

  /* Look for the number using the system call, offsetting using
     1-based counter. */
  retval = strtol( strstart, &endptr, 10 );
  if (retval == 0.0 && endptr == strstart) {
    /* conversion did not find anything */
    *jflag = 1;

    /* but SLA compatibility requires that we step
       through to remove leading spaces. We also step
       through alphabetic characters since they can never
       be numbers. Skip past a "+" since it doesn't gain
       us anything and matches slalib. */
    while (ISBLANK(*endptr) || isalpha(*endptr) || *endptr == '+' ) {
      endptr++;
    }

  } else if ( errno == ERANGE ) {
    *jflag = 2;
  } else {
    if ( retval < 0 || hasminus ) {
      *jflag = -1;
    } else {
      *jflag = 0;
    }
  }

  /* Sort out the position for the next index */
  *nstrt = endptr - string + 1;

  /* Skip a comma */
  if (*endptr == ',') {
    (*nstrt)++;
  } else {
    /* jump past any leading spaces for the next part of the string */
    ctemp = endptr;
    while ( ISBLANK(*ctemp) ) {
      (*nstrt)++;
      ctemp++;
    }
  }

  /* And the result unless we found nothing */
  if (*jflag != 1) *ireslt = retval;

}