Mercurial > hg > octave-nkf > gnulib-hg
annotate lib/parse-duration.c @ 16040:b8acd8099b25
New module 'fmaf'.
* lib/math.in.h (fmaf): New declaration.
* lib/fmaf.c: New file.
* m4/fmaf.m4: New file.
* m4/math_h.m4 (gl_MATH_H): Test whethern fmaf is declared.
(gl_MATH_H_DEFAULTS): Initialize GNULIB_FMAF, HAVE_FMAF, REPLACE_FMAF.
* modules/math (Makefile.am): Substitute GNULIB_FMAF, HAVE_FMAF,
REPLACE_FMAF.
* modules/fmaf: New file.
* doc/posix-functions/fmaf.texi: Mention the new module and the various
bugs.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Mon, 17 Oct 2011 23:51:21 +0200 |
parents | 8d1ec7b0bc4d |
children | 8250f2777afc |
rev | line source |
---|---|
10822 | 1 /* Parse a time duration and return a seconds count |
14079
97fc9a21a8fb
maint: update almost all copyright ranges to include 2011
Jim Meyering <meyering@redhat.com>
parents:
13051
diff
changeset
|
2 Copyright (C) 2008-2011 Free Software Foundation, Inc. |
10822 | 3 Written by Bruce Korb <bkorb@gnu.org>, 2008. |
4 | |
5 This program is free software: you can redistribute it and/or modify | |
6 it under the terms of the GNU General Public License as published by | |
7 the Free Software Foundation; either version 3 of the License, or | |
8 (at your option) any later version. | |
9 | |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
17 | |
18 #include <config.h> | |
19 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
20 /* Specification. */ |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
21 #include "parse-duration.h" |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
22 |
10822 | 23 #include <ctype.h> |
24 #include <errno.h> | |
25 #include <limits.h> | |
26 #include <stdio.h> | |
27 #include <stdlib.h> | |
28 #include <string.h> | |
29 | |
30 #ifndef NUL | |
31 #define NUL '\0' | |
32 #endif | |
33 | |
34 #define cch_t char const | |
35 | |
36 typedef enum { | |
37 NOTHING_IS_DONE, | |
38 YEAR_IS_DONE, | |
39 MONTH_IS_DONE, | |
40 WEEK_IS_DONE, | |
41 DAY_IS_DONE, | |
42 HOUR_IS_DONE, | |
43 MINUTE_IS_DONE, | |
44 SECOND_IS_DONE | |
45 } whats_done_t; | |
46 | |
47 #define SEC_PER_MIN 60 | |
48 #define SEC_PER_HR (SEC_PER_MIN * 60) | |
49 #define SEC_PER_DAY (SEC_PER_HR * 24) | |
50 #define SEC_PER_WEEK (SEC_PER_DAY * 7) | |
51 #define SEC_PER_MONTH (SEC_PER_DAY * 30) | |
52 #define SEC_PER_YEAR (SEC_PER_DAY * 365) | |
53 | |
54 #define TIME_MAX 0x7FFFFFFF | |
55 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
56 /* Wrapper around strtoul that does not require a cast. */ |
10822 | 57 static unsigned long inline |
58 str_const_to_ul (cch_t * str, cch_t ** ppz, int base) | |
59 { | |
60 return strtoul (str, (char **)ppz, base); | |
61 } | |
62 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
63 /* Wrapper around strtol that does not require a cast. */ |
10822 | 64 static long inline |
65 str_const_to_l (cch_t * str, cch_t ** ppz, int base) | |
66 { | |
67 return strtol (str, (char **)ppz, base); | |
68 } | |
69 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
70 /* Returns BASE + VAL * SCALE, interpreting BASE = BAD_TIME |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
71 with errno set as an error situation, and returning BAD_TIME |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
72 with errno set in an error situation. */ |
10822 | 73 static time_t inline |
74 scale_n_add (time_t base, time_t val, int scale) | |
75 { | |
76 if (base == BAD_TIME) | |
77 { | |
78 if (errno == 0) | |
79 errno = EINVAL; | |
80 return BAD_TIME; | |
81 } | |
82 | |
83 if (val > TIME_MAX / scale) | |
84 { | |
85 errno = ERANGE; | |
86 return BAD_TIME; | |
87 } | |
88 | |
89 val *= scale; | |
90 if (base > TIME_MAX - val) | |
91 { | |
92 errno = ERANGE; | |
93 return BAD_TIME; | |
94 } | |
95 | |
96 return base + val; | |
97 } | |
98 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
99 /* After a number HH has been parsed, parse subsequent :MM or :MM:SS. */ |
10822 | 100 static time_t |
101 parse_hr_min_sec (time_t start, cch_t * pz) | |
102 { | |
103 int lpct = 0; | |
104 | |
105 errno = 0; | |
106 | |
107 /* For as long as our scanner pointer points to a colon *AND* | |
108 we've not looped before, then keep looping. (two iterations max) */ | |
109 while ((*pz == ':') && (lpct++ <= 1)) | |
110 { | |
111 unsigned long v = str_const_to_ul (pz+1, &pz, 10); | |
112 | |
113 if (errno != 0) | |
114 return BAD_TIME; | |
115 | |
116 start = scale_n_add (v, start, 60); | |
117 | |
118 if (errno != 0) | |
119 return BAD_TIME; | |
120 } | |
121 | |
122 /* allow for trailing spaces */ | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
123 while (isspace ((unsigned char)*pz)) |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
124 pz++; |
10822 | 125 if (*pz != NUL) |
126 { | |
127 errno = EINVAL; | |
128 return BAD_TIME; | |
129 } | |
130 | |
131 return start; | |
132 } | |
133 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
134 /* Parses a value and returns BASE + value * SCALE, interpreting |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
135 BASE = BAD_TIME with errno set as an error situation, and returning |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
136 BAD_TIME with errno set in an error situation. */ |
10822 | 137 static time_t |
138 parse_scaled_value (time_t base, cch_t ** ppz, cch_t * endp, int scale) | |
139 { | |
140 cch_t * pz = *ppz; | |
141 time_t val; | |
142 | |
143 if (base == BAD_TIME) | |
144 return base; | |
145 | |
146 errno = 0; | |
147 val = str_const_to_ul (pz, &pz, 10); | |
148 if (errno != 0) | |
149 return BAD_TIME; | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
150 while (isspace ((unsigned char)*pz)) |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
151 pz++; |
10822 | 152 if (pz != endp) |
153 { | |
154 errno = EINVAL; | |
155 return BAD_TIME; | |
156 } | |
157 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
158 *ppz = pz; |
10822 | 159 return scale_n_add (base, val, scale); |
160 } | |
161 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
162 /* Parses the syntax YEAR-MONTH-DAY. |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
163 PS points into the string, after "YEAR", before "-MONTH-DAY". */ |
10822 | 164 static time_t |
165 parse_year_month_day (cch_t * pz, cch_t * ps) | |
166 { | |
167 time_t res = 0; | |
168 | |
169 res = parse_scaled_value (0, &pz, ps, SEC_PER_YEAR); | |
170 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
171 pz++; /* over the first '-' */ |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
172 ps = strchr (pz, '-'); |
10822 | 173 if (ps == NULL) |
174 { | |
175 errno = EINVAL; | |
176 return BAD_TIME; | |
177 } | |
178 res = parse_scaled_value (res, &pz, ps, SEC_PER_MONTH); | |
179 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
180 pz++; /* over the second '-' */ |
10822 | 181 ps = pz + strlen (pz); |
182 return parse_scaled_value (res, &pz, ps, SEC_PER_DAY); | |
183 } | |
184 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
185 /* Parses the syntax YYYYMMDD. */ |
10822 | 186 static time_t |
187 parse_yearmonthday (cch_t * in_pz) | |
188 { | |
189 time_t res = 0; | |
190 char buf[8]; | |
191 cch_t * pz; | |
192 | |
193 if (strlen (in_pz) != 8) | |
194 { | |
195 errno = EINVAL; | |
196 return BAD_TIME; | |
197 } | |
198 | |
199 memcpy (buf, in_pz, 4); | |
200 buf[4] = NUL; | |
201 pz = buf; | |
202 res = parse_scaled_value (0, &pz, buf + 4, SEC_PER_YEAR); | |
203 | |
204 memcpy (buf, in_pz + 4, 2); | |
205 buf[2] = NUL; | |
206 pz = buf; | |
207 res = parse_scaled_value (res, &pz, buf + 2, SEC_PER_MONTH); | |
208 | |
209 memcpy (buf, in_pz + 6, 2); | |
210 buf[2] = NUL; | |
211 pz = buf; | |
212 return parse_scaled_value (res, &pz, buf + 2, SEC_PER_DAY); | |
213 } | |
214 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
215 /* Parses the syntax yy Y mm M ww W dd D. */ |
10822 | 216 static time_t |
217 parse_YMWD (cch_t * pz) | |
218 { | |
219 time_t res = 0; | |
220 cch_t * ps = strchr (pz, 'Y'); | |
221 if (ps != NULL) | |
222 { | |
223 res = parse_scaled_value (0, &pz, ps, SEC_PER_YEAR); | |
224 pz++; | |
225 } | |
226 | |
227 ps = strchr (pz, 'M'); | |
228 if (ps != NULL) | |
229 { | |
230 res = parse_scaled_value (res, &pz, ps, SEC_PER_MONTH); | |
231 pz++; | |
232 } | |
233 | |
234 ps = strchr (pz, 'W'); | |
235 if (ps != NULL) | |
236 { | |
237 res = parse_scaled_value (res, &pz, ps, SEC_PER_WEEK); | |
238 pz++; | |
239 } | |
240 | |
241 ps = strchr (pz, 'D'); | |
242 if (ps != NULL) | |
243 { | |
244 res = parse_scaled_value (res, &pz, ps, SEC_PER_DAY); | |
245 pz++; | |
246 } | |
247 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
248 while (isspace ((unsigned char)*pz)) |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
249 pz++; |
10822 | 250 if (*pz != NUL) |
251 { | |
252 errno = EINVAL; | |
253 return BAD_TIME; | |
254 } | |
255 | |
256 return res; | |
257 } | |
258 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
259 /* Parses the syntax HH:MM:SS. |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
260 PS points into the string, after "HH", before ":MM:SS". */ |
10822 | 261 static time_t |
262 parse_hour_minute_second (cch_t * pz, cch_t * ps) | |
263 { | |
264 time_t res = 0; | |
265 | |
266 res = parse_scaled_value (0, &pz, ps, SEC_PER_HR); | |
267 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
268 pz++; |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
269 ps = strchr (pz, ':'); |
10822 | 270 if (ps == NULL) |
271 { | |
272 errno = EINVAL; | |
273 return BAD_TIME; | |
274 } | |
275 | |
276 res = parse_scaled_value (res, &pz, ps, SEC_PER_MIN); | |
277 | |
278 pz++; | |
279 ps = pz + strlen (pz); | |
280 return parse_scaled_value (res, &pz, ps, 1); | |
281 } | |
282 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
283 /* Parses the syntax HHMMSS. */ |
10822 | 284 static time_t |
285 parse_hourminutesecond (cch_t * in_pz) | |
286 { | |
287 time_t res = 0; | |
288 char buf[4]; | |
289 cch_t * pz; | |
290 | |
291 if (strlen (in_pz) != 6) | |
292 { | |
293 errno = EINVAL; | |
294 return BAD_TIME; | |
295 } | |
296 | |
297 memcpy (buf, in_pz, 2); | |
298 buf[2] = NUL; | |
299 pz = buf; | |
300 res = parse_scaled_value (0, &pz, buf + 2, SEC_PER_HR); | |
301 | |
302 memcpy (buf, in_pz + 2, 2); | |
303 buf[2] = NUL; | |
304 pz = buf; | |
305 res = parse_scaled_value (res, &pz, buf + 2, SEC_PER_MIN); | |
306 | |
307 memcpy (buf, in_pz + 4, 2); | |
308 buf[2] = NUL; | |
309 pz = buf; | |
310 return parse_scaled_value (res, &pz, buf + 2, 1); | |
311 } | |
312 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
313 /* Parses the syntax hh H mm M ss S. */ |
10822 | 314 static time_t |
315 parse_HMS (cch_t * pz) | |
316 { | |
317 time_t res = 0; | |
318 cch_t * ps = strchr (pz, 'H'); | |
319 if (ps != NULL) | |
320 { | |
321 res = parse_scaled_value (0, &pz, ps, SEC_PER_HR); | |
322 pz++; | |
323 } | |
324 | |
325 ps = strchr (pz, 'M'); | |
326 if (ps != NULL) | |
327 { | |
328 res = parse_scaled_value (res, &pz, ps, SEC_PER_MIN); | |
329 pz++; | |
330 } | |
331 | |
332 ps = strchr (pz, 'S'); | |
333 if (ps != NULL) | |
334 { | |
335 res = parse_scaled_value (res, &pz, ps, 1); | |
336 pz++; | |
337 } | |
338 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
339 while (isspace ((unsigned char)*pz)) |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
340 pz++; |
10822 | 341 if (*pz != NUL) |
342 { | |
343 errno = EINVAL; | |
344 return BAD_TIME; | |
345 } | |
346 | |
347 return res; | |
348 } | |
349 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
350 /* Parses a time (hours, minutes, seconds) specification in either syntax. */ |
10822 | 351 static time_t |
352 parse_time (cch_t * pz) | |
353 { | |
354 cch_t * ps; | |
355 time_t res = 0; | |
356 | |
357 /* | |
358 * Scan for a hyphen | |
359 */ | |
360 ps = strchr (pz, ':'); | |
361 if (ps != NULL) | |
362 { | |
363 res = parse_hour_minute_second (pz, ps); | |
364 } | |
365 | |
366 /* | |
367 * Try for a 'H', 'M' or 'S' suffix | |
368 */ | |
369 else if (ps = strpbrk (pz, "HMS"), | |
370 ps == NULL) | |
371 { | |
372 /* Its a YYYYMMDD format: */ | |
373 res = parse_hourminutesecond (pz); | |
374 } | |
375 | |
376 else | |
377 res = parse_HMS (pz); | |
378 | |
379 return res; | |
380 } | |
381 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
382 /* Returns a substring of the given string, with spaces at the beginning and at |
14406
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
383 the end destructively removed, per SNOBOL. */ |
10822 | 384 static char * |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
385 trim (char * pz) |
10822 | 386 { |
387 /* trim leading white space */ | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
388 while (isspace ((unsigned char)*pz)) |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
389 pz++; |
10822 | 390 |
391 /* trim trailing white space */ | |
392 { | |
393 char * pe = pz + strlen (pz); | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
394 while ((pe > pz) && isspace ((unsigned char)pe[-1])) |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
395 pe--; |
10822 | 396 *pe = NUL; |
397 } | |
398 | |
399 return pz; | |
400 } | |
401 | |
402 /* | |
403 * Parse the year/months/days of a time period | |
404 */ | |
405 static time_t | |
406 parse_period (cch_t * in_pz) | |
407 { | |
14406
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
408 char * pT; |
10822 | 409 char * ps; |
14406
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
410 char * pz = strdup (in_pz); |
10822 | 411 void * fptr = pz; |
412 time_t res = 0; | |
413 | |
14406
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
414 if (pz == NULL) |
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
415 { |
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
416 errno = ENOMEM; |
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
417 return BAD_TIME; |
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
418 } |
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
419 |
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
420 pT = strchr (pz, 'T'); |
8d1ec7b0bc4d
parse-duration: remove xalloc.h dependency
Bruce Korb <bkorb@gnu.org>
parents:
14079
diff
changeset
|
421 if (pT != NULL) |
10822 | 422 { |
423 *(pT++) = NUL; | |
424 pz = trim (pz); | |
425 pT = trim (pT); | |
426 } | |
427 | |
428 /* | |
429 * Scan for a hyphen | |
430 */ | |
431 ps = strchr (pz, '-'); | |
432 if (ps != NULL) | |
433 { | |
434 res = parse_year_month_day (pz, ps); | |
435 } | |
436 | |
437 /* | |
438 * Try for a 'Y', 'M' or 'D' suffix | |
439 */ | |
440 else if (ps = strpbrk (pz, "YMWD"), | |
441 ps == NULL) | |
442 { | |
443 /* Its a YYYYMMDD format: */ | |
444 res = parse_yearmonthday (pz); | |
445 } | |
446 | |
447 else | |
448 res = parse_YMWD (pz); | |
449 | |
450 if ((errno == 0) && (pT != NULL)) | |
451 { | |
452 time_t val = parse_time (pT); | |
453 res = scale_n_add (res, val, 1); | |
454 } | |
455 | |
456 free (fptr); | |
457 return res; | |
458 } | |
459 | |
460 static time_t | |
13051 | 461 parse_non_iso8601 (cch_t * pz) |
10822 | 462 { |
463 whats_done_t whatd_we_do = NOTHING_IS_DONE; | |
464 | |
465 time_t res = 0; | |
466 | |
467 do { | |
468 time_t val; | |
469 | |
470 errno = 0; | |
471 val = str_const_to_l (pz, &pz, 10); | |
472 if (errno != 0) | |
473 goto bad_time; | |
474 | |
475 /* IF we find a colon, then we're going to have a seconds value. | |
476 We will not loop here any more. We cannot already have parsed | |
477 a minute value and if we've parsed an hour value, then the result | |
478 value has to be less than an hour. */ | |
479 if (*pz == ':') | |
480 { | |
481 if (whatd_we_do >= MINUTE_IS_DONE) | |
482 break; | |
483 | |
484 val = parse_hr_min_sec (val, pz); | |
485 | |
486 if ((whatd_we_do == HOUR_IS_DONE) && (val >= SEC_PER_HR)) | |
487 break; | |
488 | |
489 return scale_n_add (res, val, 1); | |
490 } | |
491 | |
492 { | |
493 unsigned int mult; | |
494 | |
495 /* Skip over white space following the number we just parsed. */ | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
496 while (isspace ((unsigned char)*pz)) |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
497 pz++; |
10822 | 498 |
499 switch (*pz) | |
500 { | |
501 default: goto bad_time; | |
502 case NUL: | |
503 return scale_n_add (res, val, 1); | |
504 | |
505 case 'y': case 'Y': | |
506 if (whatd_we_do >= YEAR_IS_DONE) | |
507 goto bad_time; | |
508 mult = SEC_PER_YEAR; | |
509 whatd_we_do = YEAR_IS_DONE; | |
510 break; | |
511 | |
512 case 'M': | |
513 if (whatd_we_do >= MONTH_IS_DONE) | |
514 goto bad_time; | |
515 mult = SEC_PER_MONTH; | |
516 whatd_we_do = MONTH_IS_DONE; | |
517 break; | |
518 | |
519 case 'W': | |
520 if (whatd_we_do >= WEEK_IS_DONE) | |
521 goto bad_time; | |
522 mult = SEC_PER_WEEK; | |
523 whatd_we_do = WEEK_IS_DONE; | |
524 break; | |
525 | |
526 case 'd': case 'D': | |
527 if (whatd_we_do >= DAY_IS_DONE) | |
528 goto bad_time; | |
529 mult = SEC_PER_DAY; | |
530 whatd_we_do = DAY_IS_DONE; | |
531 break; | |
532 | |
533 case 'h': | |
534 if (whatd_we_do >= HOUR_IS_DONE) | |
535 goto bad_time; | |
536 mult = SEC_PER_HR; | |
537 whatd_we_do = HOUR_IS_DONE; | |
538 break; | |
539 | |
540 case 'm': | |
541 if (whatd_we_do >= MINUTE_IS_DONE) | |
542 goto bad_time; | |
543 mult = SEC_PER_MIN; | |
544 whatd_we_do = MINUTE_IS_DONE; | |
545 break; | |
546 | |
547 case 's': | |
548 mult = 1; | |
549 whatd_we_do = SECOND_IS_DONE; | |
550 break; | |
551 } | |
552 | |
553 res = scale_n_add (res, val, mult); | |
554 | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
555 pz++; |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
556 while (isspace ((unsigned char)*pz)) |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
557 pz++; |
10822 | 558 if (*pz == NUL) |
559 return res; | |
560 | |
561 if (! isdigit ((unsigned char)*pz)) | |
562 break; | |
563 } | |
564 | |
565 } while (whatd_we_do < SECOND_IS_DONE); | |
566 | |
567 bad_time: | |
568 errno = EINVAL; | |
569 return BAD_TIME; | |
570 } | |
571 | |
572 time_t | |
573 parse_duration (char const * pz) | |
574 { | |
10890
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
575 while (isspace ((unsigned char)*pz)) |
195c41817bd2
parse-duration: various small improvements.
Bruno Haible <bruno@clisp.org>
parents:
10866
diff
changeset
|
576 pz++; |
10822 | 577 |
10978
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
578 switch (*pz) |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
579 { |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
580 case 'P': |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
581 return parse_period (pz + 1); |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
582 |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
583 case 'T': |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
584 return parse_time (pz + 1); |
10822 | 585 |
10978
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
586 default: |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
587 if (isdigit ((unsigned char)*pz)) |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
588 return parse_non_iso8601 (pz); |
10822 | 589 |
10978
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
590 errno = EINVAL; |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
591 return BAD_TIME; |
1780a93bb27f
parse-duration: small doc tweak and coding aesthetics issue.
Bruce Korb <bkorb@gnu.org>
parents:
10890
diff
changeset
|
592 } |
10822 | 593 } |
594 | |
595 /* | |
596 * Local Variables: | |
597 * mode: C | |
598 * c-file-style: "gnu" | |
599 * indent-tabs-mode: nil | |
600 * End: | |
601 * end of parse-duration.c */ |