1 /*-------------- Telecommunications & Signal Processing Lab ---------------
2 McGill University
3
4 Routine:
5 int STdec1val (const char String[], int Type, void *Val)
6
7 Purpose:
8 Decode a numeric value
9
10 Description:
11 This routine decodes a string containing a numeric value. The data type can
12 be specified. If a decoding error is detected, a warning message is printed
13 and an error status value is returned.
14
15 Parameters:
16 <- int STdec1val
17 Error status,
18 0 - no error
19 1 - format error
20 2 - range warning
21 -> const char String[]
22 Input string
23 -> int Type
24 Code for the data type, 'D' for double, 'F' for float, 'I' for int, 'L'
25 for long int.
26 <- void *Val
27 Returned value of the type indicated by Type. This value is not changed
28 for a format error. For a range warning, the returned value is set to
29 the appropriate representable value.
30
31 Author / revision:
32 P. Kabal Copyright (C) 2003
33 $Revision: 1.22 $ $Date: 2003/05/09 03:17:00 $
34
35 -------------------------------------------------------------------------*/
36
37 #include <assert.h>
38 #include <ctype.h>
39 #include <errno.h>
40 #include <float.h>
41 #include <limits.h>
42 #include <stdlib.h> /* strtod */
43
44
45 #include <libtsp.h>
46 #include <libtsp/nucleus.h>
47 #include <libtsp/STmsg.h>
48
49 #define ABSV(x) (((x) < 0) ? -(x) : (x))
50
51 #define MAXC 23
52
53
54 int
STdec1val(const char String[],int Type,void * Val)55 STdec1val (const char String[], int Type, void *Val)
56
57 {
58 int BS;
59 double dv;
60 long int lv;
61 char *endstr;
62
63 /* Trim initial white space */
64 for (; isspace ((int) *String); ++String)
65 ;
66 if (String[0] == '\0') {
67 UTwarn ("STdec1val - %s", STM_EmptyData);
68 return 1;
69 }
70
71 /* Note: strtol should clamp a large input to INT_MAX, but the SunOS 4
72 version wraps the value around instead, with no ERANGE errcode. (This
73 is documented in the man page: "Overflow conditions are ignored.")
74 */
75
76 dv = 0.0; /* stop compiler warnings */
77 lv = 0;
78 errno = 0;
79 BS = 0;
80 switch (Type) {
81 case 'D':
82 case 'F':
83 dv = strtod (String, &endstr);
84 if (errno == ERANGE) {
85 if (dv == 0.0)
86 BS = -1;
87 else
88 BS = 1;
89 }
90 break;
91 case 'L':
92 case 'I':
93 lv = strtol (String, &endstr, 10);
94 if (errno == ERANGE)
95 BS = 1;
96 break;
97 default:
98 assert (0);
99 break;
100 }
101
102 /* Trim white space on endstr */
103 for (; isspace ((int) *endstr); ++endstr)
104 ;
105 if (endstr[0] != '\0') {
106 /* Data format error */
107 UTwarn ("STdec1val - %s: \"%s\"", STM_DataErr, STstrDots (String, MAXC));
108 return 1;
109 }
110
111 /* Return a value of the correct type */
112 switch (Type) {
113 case 'D':
114 *((double *) Val) = dv;
115 break;
116 case 'F':
117 if (dv > FLT_MAX) {
118 dv = FLT_MAX;
119 BS = 1;
120 }
121 else if (dv < -FLT_MAX) {
122 dv = -FLT_MAX;
123 BS = 1;
124 }
125 else if (dv != 0.0 && ABSV (dv) < FLT_MIN) {
126 dv = 0.0;
127 BS = -1;
128 }
129 *((float *) Val) = (float) dv;
130 break;
131 case 'L':
132 *((long int *) Val) = lv;
133 break;
134 case 'I':
135 #if (INT_MAX != LONG_MAX)
136 if (lv < INT_MIN) {
137 lv = INT_MIN;
138 BS = +1;
139 }
140 else if (lv > INT_MAX) {
141 lv = INT_MAX;
142 BS = +1;
143 }
144 #else
145 *((int *) Val) = lv;
146 #endif
147 break;
148 }
149
150 if (BS < 0)
151 UTwarn ("STdec1val - %s: \"%s\"", STM_SmallVal, STstrDots (String, MAXC));
152 else if (BS > 0)
153 UTwarn ("STdec1val - %s: \"%s\"", STM_BigVal, STstrDots (String, MAXC));
154
155 /* Return the status value */
156 if (BS != 0)
157 return 2;
158 else
159 return 0;
160 }
161