Neale Pickett
·
2017-08-05
timerfc.c
1/*
2 * Code in this file is from mathopd <http://www.mathopd.org/>
3 *
4 * Copyright 1996, Michiel Boland.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
9 * conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials
18 * provided with the distribution.
19 *
20 * 3. The name of the author may not be used to endorse or promote
21 * products derived from this software without specific prior
22 * written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
25 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
30 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35 * THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <time.h>
39#include <ctype.h>
40#include <string.h>
41#include "timerfc.h"
42
43time_t
44timerfc(const char *s)
45{
46 static const int daytab[2][12] = {
47 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
48 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
49 };
50 unsigned sec,
51 min,
52 hour,
53 day,
54 mon,
55 year;
56 char month[3];
57 int c;
58 unsigned n;
59 char flag;
60 char state;
61 char isctime;
62 enum { D_START, D_END, D_MON, D_DAY, D_YEAR, D_HOUR, D_MIN, D_SEC };
63
64 sec = 60;
65 min = 60;
66 hour = 24;
67 day = 32;
68 year = 1969;
69 isctime = 0;
70 month[0] = 0;
71 state = D_START;
72 n = 0;
73 flag = 1;
74 do {
75 c = *s++;
76 switch (state) {
77 case D_START:
78 if (c == ' ') {
79 state = D_MON;
80 isctime = 1;
81 } else if (c == ',')
82 state = D_DAY;
83 break;
84 case D_MON:
85 if (isalpha(c)) {
86 if (n < 3)
87 month[n++] = c;
88 } else {
89 if (n < 3)
90 return -1;
91 n = 0;
92 state = isctime ? D_DAY : D_YEAR;
93 }
94 break;
95 case D_DAY:
96 if (c == ' ' && flag);
97 else if (isdigit(c)) {
98 flag = 0;
99 n = 10 * n + (c - '0');
100 } else {
101 day = n;
102 n = 0;
103 state = isctime ? D_HOUR : D_MON;
104 }
105 break;
106 case D_YEAR:
107 if (isdigit(c))
108 n = 10 * n + (c - '0');
109 else {
110 year = n;
111 n = 0;
112 state = isctime ? D_END : D_HOUR;
113 }
114 break;
115 case D_HOUR:
116 if (isdigit(c))
117 n = 10 * n + (c - '0');
118 else {
119 hour = n;
120 n = 0;
121 state = D_MIN;
122 }
123 break;
124 case D_MIN:
125 if (isdigit(c))
126 n = 10 * n + (c - '0');
127 else {
128 min = n;
129 n = 0;
130 state = D_SEC;
131 }
132 break;
133 case D_SEC:
134 if (isdigit(c))
135 n = 10 * n + (c - '0');
136 else {
137 sec = n;
138 n = 0;
139 state = isctime ? D_YEAR : D_END;
140 }
141 break;
142 }
143 } while (state != D_END && c);
144 switch (month[0]) {
145 case 'A':
146 mon = (month[1] == 'p') ? 4 : 8;
147 break;
148 case 'D':
149 mon = 12;
150 break;
151 case 'F':
152 mon = 2;
153 break;
154 case 'J':
155 mon = (month[1] == 'a') ? 1 : ((month[2] == 'l') ? 7 : 6);
156 break;
157 case 'M':
158 mon = (month[2] == 'r') ? 3 : 5;
159 break;
160 case 'N':
161 mon = 11;
162 break;
163 case 'O':
164 mon = 10;
165 break;
166 case 'S':
167 mon = 9;
168 break;
169 default:
170 return -1;
171 }
172 if (year <= 100)
173 year += (year < 70) ? 2000 : 1900;
174 --mon;
175 --day;
176 if (sec >= 60 || min >= 60 || hour >= 60 || day >= 31)
177 return -1;
178 if (year < 1970)
179 return 0;
180 return sec + 60L * (min + 60L * (hour + 24L * (day +
181 daytab[year % 4 == 0
182 && (year % 100
183 || year %
184 400 ==
185 0)][mon] +
186 365L * (year - 1970L) +
187 ((year -
188 1969L) >> 2))));
189}
190
191char *
192rfctime(time_t t, char *buf)
193{
194 struct tm *tp;
195
196 /* ntp: in glibc, this triggers a bunch of needless I/O. */
197 tp = gmtime(&t);
198 if (tp == 0) {
199 strcpy(buf, "?");
200 return buf;
201 }
202 strftime(buf, 31, "%a, %d %b %Y %H:%M:%S GMT", tp);
203 return buf;
204}