scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <string.h>
  4#include <time.h>
  5
  6#include "../../libc.h"
  7
  8#define TOKENSIZ 10
  9
 10enum {
 11	EOS,
 12	NUM,
 13	STR,
 14};
 15
 16enum {
 17	GREGORIAN,
 18	JULIAN,
 19};
 20
 21int _daylight;
 22char *_tzname[2];
 23long _timezone, _dstzone;
 24
 25static int tok;
 26static char tokstr[TOKENSIZ];
 27
 28static int sjulian, start;
 29static int ejulian, end;
 30static long shour, ehour;
 31
 32static int
 33next(char *str)
 34{
 35	int n, t;
 36	static char *s;
 37
 38	if (str)
 39		s = str;
 40
 41	switch (*s) {
 42	case '0':
 43	case '1':
 44	case '2':
 45	case '3':
 46	case '4':
 47	case '5':
 48	case '6':
 49	case '7':
 50	case '8':
 51	case '9':
 52		n = strspn(s, "0123456789");
 53		t = NUM;
 54		break;
 55	case '/':
 56	case '+':
 57	case '-':
 58	case ':':
 59	case ',':
 60		n = 1;
 61		t = *s;
 62		break;
 63	case '\0':
 64		n = 0;
 65		t = EOS;
 66		break;
 67	default:
 68		n = strcspn(s, "+-0123456789,/");
 69		t = STR;
 70		break;
 71	}
 72
 73	if (n >= TOKENSIZ-1)
 74		return -1;
 75	memcpy(tokstr, s, n);
 76	tokstr[n] = '\0';
 77	s += n;
 78
 79	return tok = t;
 80}
 81
 82static int
 83accept(int c)
 84{
 85	if (tok != c)
 86		return 0;
 87	return next(NULL);
 88}
 89
 90static int
 91num(int max)
 92{
 93	int n;
 94
 95	if (tok != NUM)
 96		return -1;
 97	n = atoi(tokstr);
 98	if (n < 0 || n > max)
 99		return -1;
100	return n;
101}
102
103static long
104offset(void)
105{
106	long off;
107	int n, sign = 1;
108
109	if (tok == EOS)
110		return -1;
111
112	switch (tok) {
113	case '-':
114		sign = -1;
115	case '+':
116		next(NULL);
117		break;
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		goto ret;
129	if ((n = num(60)) < 0)
130		return -1;
131	off += n * SECMIN;
132	next(NULL);
133
134	if (!accept(':'))
135		goto ret;
136	if ((n = num(60)) < 0)
137		return -1;
138	off += n;
139	next(NULL);
140
141 ret:
142	return sign * off;
143}
144
145static int
146std(void)
147{
148	long off;
149	char *name;
150
151	if ((name = _gmtoff(tokstr)) == NULL)
152		return 0;
153
154	next(NULL);
155	if ((off = offset()) == -1)
156		return 0;
157
158	_tzname[0] = name;
159	_timezone = off;
160
161	return 1;
162}
163
164static int
165dst(void)
166{
167	long off;
168	char *name;
169
170	if ((name = _gmtoff(tokstr)) == NULL)
171		return 0;
172	_tzname[1] = name;
173
174	next(NULL);
175	if ((off = offset()) == -1)
176		_dstzone = _timezone - SECHOUR;
177	else
178		_dstzone = off;
179
180	return _daylight = 1;
181}
182
183static int
184yday(int *julian, long *hour)
185{
186	long off;
187	int type, n;
188
189	if (tok == STR && !strcmp(tokstr, "J"))
190		type = JULIAN;
191	else if (tok == NUM)
192		type = GREGORIAN;
193	else
194		return -1;
195
196	switch (type) {
197	case JULIAN:
198		*julian = 1;
199		next(NULL);
200		n = num(365);
201		next(NULL);
202		if (n == 0)
203			return -1;
204		n--;
205		break;
206	case GREGORIAN:
207		*julian = 0;
208		n = num(365);
209		next(NULL);
210		break;
211	}
212	if (accept('/')) {
213		if ((off = offset()) < 0)
214			return -1;
215		*hour = off;
216	}
217	return n;
218}
219
220static int
221rule(void)
222{
223	shour = ehour = 2 * SECHOUR;
224
225	if (!accept(','))
226		return 0;
227	if ((start = yday(&sjulian, &shour)) == -1)
228		return 0;
229	if (!accept(','))
230		return 0;
231	if ((end = yday(&ejulian, &ehour)) == -1)
232		return 0;
233}
234
235void
236_tzset(void)
237{
238	static char *tz;
239	static char cache[80];
240	char *s = getenv("TZ");
241
242	if (s) {
243		if (tz && strcmp(s, tz) == 0)
244			return;
245		snprintf(cache, sizeof(cache), "%s", s);
246		tz = cache;
247	}
248
249	if (!s || next(s) == EOS)
250		goto error;
251
252	start = end = -1;
253
254	if (!std())
255		goto error;
256	if (tok == EOS)
257		goto adjust;
258
259	if (!dst())
260		goto error;
261	if (tok == EOS)
262		goto adjust;
263
264	if (!rule())
265		goto error;
266	if (tok != EOS)
267		goto error;
268
269adjust:
270	if (!_daylight) {
271		_tzname[1] = _tzname[0];
272		_dstzone = _timezone;
273	}
274
275	return;
276
277error:
278	_daylight = 0;
279	_tzname[1] = _tzname[0] = "UTC";
280	_timezone = _dstzone = 0;
281}
282
283int
284_isdst(struct tm *tm)
285{
286	long off;
287	int day, bis, yday;
288
289	if (!_daylight)
290		return 0;
291
292	bis = FEBDAYS(tm->tm_year) == 29;
293	yday = tm->tm_yday;
294	off = tm->tm_hour * SECHOUR;
295	off += tm->tm_min * SECMIN;
296	off += tm->tm_sec;
297
298	day = start;
299	if (sjulian && bis && day >= 59)
300		day++;
301	if (yday < day || yday == day && off < shour)
302		return 0;
303
304	day = end;
305	if (ejulian && bis && day >= 59)
306		day++;
307	if (yday > day || yday == day && off > ehour)
308		return 0;
309
310	return 1;
311}