scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | 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 }