Home
       _tzone.c - scc - simple c99 compiler
  HTML 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 }