File Coverage

palsrc/palIntin.c
Criterion Covered Total %
statement 22 27 81.4
branch 12 26 46.1
condition n/a
subroutine n/a
pod n/a
total 34 53 64.1


line stmt bran cond sub pod time code
1             /*
2             *+
3             * Name:
4             * palIntin
5              
6             * Purpose:
7             * Convert free-format input into an integer
8              
9             * Language:
10             * Starlink ANSI C
11              
12             * Type of Module:
13             * Library routine
14              
15             * Invocation:
16             * void palIntin( const char * string, int *nstrt,
17             * long *ireslt, int *jflag );
18              
19             * Arguments:
20             * string = const char * (Given)
21             * String containing number to be decoded.
22             * nstrt = int * (Given and Returned)
23             * Character number indicating where decoding should start.
24             * On output its value is updated to be the location of the
25             * possible next value. For compatibility with SLA the first
26             * character is index 1.
27             * ireslt = long * (Returned)
28             * Result. Not updated when jflag=1.
29             * jflag = int * (Returned)
30             * status: -1 = -OK, 0 = +OK, 1 = null, 2 = error
31              
32             * Description:
33             * Extracts a number from an input string starting at the specified
34             * index.
35              
36             * Authors:
37             * TIMJ: Tim Jenness (JAC, Hawaii)
38             * {enter_new_authors_here}
39              
40             * Notes:
41             * - Uses the strtol() system call to do the parsing. This may lead to
42             * subtle differences when compared to the SLA/F parsing.
43             * - Commas are recognized as a special case and are skipped if one happens
44             * to be the next character when updating nstrt. Additionally the output
45             * nstrt position will skip past any trailing space.
46             * - If no number can be found flag will be set to 1.
47             * - If the number overflows or underflows jflag will be set to 2. For overflow
48             * the returned result will have the value LONG_MAX, for underflow it
49             * will have the value LONG_MIN.
50              
51             * History:
52             * 2012-03-15 (TIMJ):
53             * Initial version
54             * Matches the SLALIB interface but brand new implementation using
55             * C library calls and not a direct port of the Fortran.
56             * 2014-08-07 (TIMJ):
57             * Check for isblank availability.
58             * {enter_further_changes_here}
59              
60             * Copyright:
61             * Copyright (C) 2012,2014 Science and Technology Facilities Council.
62             * All Rights Reserved.
63              
64             * Licence:
65             * This program is free software; you can redistribute it and/or
66             * modify it under the terms of the GNU General Public License as
67             * published by the Free Software Foundation; either version 3 of
68             * the License, or (at your option) any later version.
69             *
70             * This program is distributed in the hope that it will be
71             * useful, but WITHOUT ANY WARRANTY; without even the implied
72             * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
73             * PURPOSE. See the GNU General Public License for more details.
74             *
75             * You should have received a copy of the GNU General Public License
76             * along with this program; if not, write to the Free Software
77             * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
78             * MA 02110-1301, USA.
79              
80             * Bugs:
81             * {note_any_bugs_here}
82             *-
83             */
84              
85             #if HAVE_CONFIG_H
86             # include
87             #endif
88              
89             #include
90             #include
91              
92             /* isblank() is a C99 feature so we just reimplement it if it is missing */
93             #if HAVE_ISBLANK
94             #ifndef _ISOC99_SOURCE
95             #define _ISOC99_SOURCE
96             #endif
97             #include
98             # define ISBLANK isblank
99             #else
100              
101             static int ISBLANK( int c ) {
102 10           return ( c == ' ' || c == '\t' );
103             }
104              
105             #endif
106              
107             /* Still need ctype for isalpha and isdigit */
108             #include
109              
110             #include "pal.h"
111              
112 6           void palIntin( const char * string, int *nstrt,
113             long *ireslt, int *jflag ) {
114              
115             const char *strstart = NULL; /* Pointer to start of search */
116             const char * ctemp = NULL; /* Pointer into string */
117 6           char * endptr = NULL;/* Pointer to string after number */
118             int retval; /* Return value from strtol */
119             int hasminus; /* is this a -0 */
120              
121             /* strtol man page indicates that we should reset errno before
122             calling strtod */
123 6           errno = 0;
124              
125             /* Locate the start postion */
126 6           strstart = &(string[*nstrt-1]);
127              
128             /* We have to be able to deal with -0 so we have to search the
129             string first and look for the negative */
130             hasminus = 0;
131             ctemp = strstart;
132 7 50         while ( ctemp != '\0' ) {
133 7 100         if (isdigit(*ctemp)) break;
134             /* Reset so that - 12345 is not a negative number */
135             hasminus = 0;
136             /* Flag that we have found a minus */
137 1 50         if (*ctemp == '-') hasminus = 1;
138 1           ctemp++;
139             }
140              
141             /* Look for the number using the system call, offsetting using
142             1-based counter. */
143 6           retval = strtol( strstart, &endptr, 10 );
144 6 50         if (retval == 0.0 && endptr == strstart) {
    0          
145             /* conversion did not find anything */
146 0           *jflag = 1;
147              
148             /* but SLA compatibility requires that we step
149             through to remove leading spaces. We also step
150             through alphabetic characters since they can never
151             be numbers. Skip past a "+" since it doesn't gain
152             us anything and matches slalib. */
153 0 0         while (ISBLANK(*endptr) || isalpha(*endptr) || *endptr == '+' ) {
    0          
    0          
154 0           endptr++;
155             }
156              
157 6 50         } else if ( errno == ERANGE ) {
158 0           *jflag = 2;
159             } else {
160 6 100         if ( retval < 0 || hasminus ) {
161 1           *jflag = -1;
162             } else {
163 5           *jflag = 0;
164             }
165             }
166              
167             /* Sort out the position for the next index */
168 6           *nstrt = endptr - string + 1;
169              
170             /* Skip a comma */
171 6 50         if (*endptr == ',') {
172 0           (*nstrt)++;
173             } else {
174             /* jump past any leading spaces for the next part of the string */
175             ctemp = endptr;
176 10 100         while ( ISBLANK(*ctemp) ) {
177 4           (*nstrt)++;
178 4           ctemp++;
179             }
180             }
181              
182             /* And the result unless we found nothing */
183 6 50         if (*jflag != 1) *ireslt = retval;
184              
185 6           }