_tzone.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
_tzone.c (2869B)
---
1 #include <stdlib.h>
2 #include <string.h>
3 #include <time.h>
4
5 #include "../../libc.h"
6
7 #define TOKENSIZ 10
8
9 enum {
10 EOS,
11 NUM,
12 STR,
13 };
14
15 enum {
16 GREGORIAN,
17 JULIAN,
18 };
19
20 static char st[TOKENSIZ], ds[TOKENSIZ], tokstr[TOKENSIZ];
21 static int tok;
22
23 char *_tzname[2] = { st, ds };
24 time_t _tzstdoff, _tzdstoff;
25 time_t _tzstart, _tzend;
26 int _tzjulian;
27
28 static int
29 next(char *str)
30 {
31 int n, t;
32 static char *s;
33
34 if (str)
35 s = str;
36
37 switch (*s) {
38 case '0':
39 case '1':
40 case '2':
41 case '3':
42 case '4':
43 case '5':
44 case '6':
45 case '7':
46 case '8':
47 case '9':
48 n = strspn(s, "0123456789");
49 t = NUM;
50 break;
51 case '+':
52 case '-':
53 case ':':
54 case ',':
55 n = 1;
56 t = *s;
57 break;
58 case '\0':
59 n = 0;
60 t = EOS;
61 break;
62 default:
63 n = strcspn(s, "+-0123456789");
64 t = STR;
65 break;
66 }
67
68 if (n >= TOKENSIZ-1)
69 return -1;
70 memcpy(tokstr, s, n);
71 tokstr[n] = '\0';
72 s += n;
73
74 return tok = t;
75 }
76
77 static int
78 accept(int c)
79 {
80 if (tok != c)
81 return 0;
82 return next(NULL);
83 }
84
85 static int
86 num(int max)
87 {
88 int n;
89
90 if (tok == EOS)
91 return 0;
92 if (tok != NUM)
93 return -1;
94 n = atoi(tokstr);
95 if (n < 0 || n > max)
96 return -1;
97 return n;
98 }
99
100 static long
101 offset(void)
102 {
103 int sign = 1;
104 int n;
105 long off;
106
107 if (tok == EOS)
108 return -1;
109
110 switch (tok) {
111 case '+':
112 sign = -1;
113 case '-':
114 next(NULL);
115 break;
116 default:
117 return -1;
118 }
119
120 if ((n = num(24)) < 0)
121 return -1;
122 off = n * SECHOUR;
123 next(NULL);
124 if (tok == EOS)
125 goto ret;
126
127 if (!accept(':'))
128 return -1;
129 if ((n = num(60)) < 0)
130 return -1;
131 off += n * SECMIN;
132 next(NULL);
133 if (tok == EOS)
134 goto ret;
135
136 if (!accept(':'))
137 return -1;
138 if ((n = num(60)) < 0)
139 return -1;
140 off += n;
141 next(NULL);
142
143 ret:
144 return sign * off;
145 }
146
147 static int
148 std(void)
149 {
150 time_t off;
151
152 if (tok != STR)
153 return 0;
154 strcpy(st, tokstr);
155 next(NULL);
156
157 if ((off = offset()) == -1)
158 return 0;
159 _tzstdoff = off;
160
161 return 1;
162 }
163
164 static int
165 dst(void)
166 {
167 time_t off;
168
169 if (tok != STR)
170 return 0;
171 strcpy(ds, tokstr);
172 next(NULL);
173
174 if ((off = offset()) == -1)
175 _tzdstoff = off;
176 else
177 _tzdstoff = _tzstdoff + SECHOUR;
178
179 return 1;
180 }
181
182 static int
183 yday(void)
184 {
185 int type, n;
186
187 if (tok == STR && !strcmp(tokstr, "J"))
188 type = JULIAN;
189 else if (tok == NUM)
190 type = GREGORIAN;
191 else
192 return -1;
193
194 switch (type) {
195 case JULIAN:
196 next(NULL);
197 n = num(365);
198 next(NULL);
199 if (n == 0)
200 return -1;
201 _tzjulian = 1;
202 break;
203 case GREGORIAN:
204 n = num(365);
205 next(NULL);
206 break;
207 }
208
209 return n;
210 }
211
212 static int
213 rule(void)
214 {
215 if (tok == EOS)
216 return 0;
217 if (!accept(','))
218 return 0;
219 if ((_tzstart = yday()) == -1)
220 return 0;
221 if (!accept(','))
222 return 0;
223 if ((_tzend = yday()) == -1)
224 return 0;
225 }
226
227 void
228 _tzset(void)
229 {
230 char *tz = getenv("TZ");
231 int i;
232
233 _tzstdoff = _tzdstoff = (time_t) -1;
234 _tzstart = _tzend = (time_t) -1;
235 _tzjulian = 0;
236
237 if (!tz)
238 return;
239 next(tz);
240
241 if (!std())
242 return;
243 if (!dst())
244 return;
245 if (!rule())
246 return;
247 }