Moved date/time functions from zotnet/tws to sbr. More importantly,
[mmh] / sbr / dtimep.lex
1 %option noyywrap
2 %{
3 #include <h/nmh.h>
4 #include <h/tws.h>
5
6 #define YY_NO_UNPUT
7 #define YY_DECL struct tws * dparsetime(char *lexstr)
8
9 #define yyterminate() (void)yy_delete_buffer(lexhandle); \
10   if(!(tw.tw_flags & TW_SUCC)) { \
11     return (struct tws *)NULL; \
12   } \
13   if(tw.tw_year < 1960) \
14     tw.tw_year += 1900; \
15   if(tw.tw_year < 1960) \
16     tw.tw_year += 100; \
17   return(&tw)
18
19 /*
20  * Patchable flag that says how to interpret NN/NN/NN dates. When
21  * true, we do it European style: DD/MM/YY. When false, we do it
22  * American style: MM/DD/YY.  Of course, these are all non-RFC822
23  * compliant.
24  */
25 int europeandate = 0;
26
27 /*
28  * Table to convert month names to numeric month.  We use the
29  * fact that the low order 5 bits of the sum of the 2nd & 3rd
30  * characters of the name is a hash with no collisions for the 12
31  * valid month names.  (The mask to 5 bits maps any combination of
32  * upper and lower case into the same hash value).
33  */
34 static int month_map[] = {
35         0,
36         6,      /* 1 - Jul */
37         3,      /* 2 - Apr */
38         5,      /* 3 - Jun */
39         0,
40         10,     /* 5 - Nov */
41         0,
42         1,      /* 7 - Feb */
43         11,     /* 8 - Dec */
44         0,
45         0,
46         0,
47         0,
48         0,
49         0,
50         0,      /*15 - Jan */
51         0,
52         0,
53         0,
54         2,      /*19 - Mar */
55         0,
56         8,      /*21 - Sep */
57         0,
58         9,      /*23 - Oct */
59         0,
60         0,
61         4,      /*26 - May */
62         0,
63         7       /*28 - Aug */
64 };
65
66 /*
67  * Same trick for day-of-week using the hash function
68  *  (c1 & 7) + (c2 & 4)
69  */
70 static int day_map[] = {
71         0,
72         0,
73         0,
74         6,      /* 3 - Sat */
75         4,      /* 4 - Thu */
76         0,
77         5,      /* 6 - Fri */
78         0,      /* 7 - Sun */
79         2,      /* 8 - Tue */
80         1       /* 9 - Mon */,
81         0,
82         3       /*11 - Wed */
83 };
84
85 #define INIT()   { cp = yytext;}
86 #define SETWDAY() { cp++; \
87                    tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)]; \
88                    tw.tw_flags &= ~TW_SDAY; tw.tw_flags |= TW_SEXP; \
89                    SKIPA(); }
90 #define SETMON() { cp++; \
91                    tw.tw_mon = month_map[(cp[0] + cp[1]) & 0x1f]; \
92                    SKIPA(); }
93 #define SETMON_NUM() { tw.tw_mon = atoi(cp)-1; \
94                    SKIPD(); }
95 #define SETYEAR() { tw.tw_year = atoi(cp); \
96                    SKIPD(); }
97 #define SETDAY() { tw.tw_mday = atoi(cp); \
98                    tw.tw_flags |= TW_YES; \
99                    SKIPD(); }
100 #define SETTIME() { tw.tw_hour = atoi(cp); \
101                     cp += 2; \
102                     SKIPTOD(); \
103                     tw.tw_min = atoi(cp); \
104                     cp += 2; \
105                     if(*cp == ':') { tw.tw_sec = atoi(++cp); SKIPD(); } \
106                     }
107 #define SETZONE(x) { tw.tw_zone = ((x)/100)*60+(x)%100; \
108                      tw.tw_flags |= TW_SZEXP; \
109                      SKIPD(); }
110 #define SETDST()   { tw.tw_flags |= TW_DST; }
111 #define SKIPD()  { while ( isdigit(*cp++) ) ; \
112                       --cp; }
113 #define SKIPTOD()  { while ( !isdigit(*cp++) ) ; \
114                       --cp; }
115 #define SKIPA()  { while ( isalpha(*cp++) ) ; \
116                       --cp; }
117 #define SKIPTOA()  { while ( !isalpha(*cp++) ) ; \
118                       --cp; }
119 #define SKIPSP()  { while ( isspace(*cp++) ) ; \
120                       --cp; }
121 #define SKIPTOSP()  { while ( !isspace(*cp++) ) ; \
122                       --cp; }
123 %}
124
125 sun     (sun(day)?)
126 mon     (mon(day)?)
127 tue     (tue(sday)?)
128 wed     (wed(nesday)?)
129 thu     (thu(rsday)?)
130 fri     (fri(day)?)
131 sat     (sat(urday)?)
132
133 DAY     ({sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat})
134
135 jan     (jan(uary)?)
136 feb     (feb(ruary)?)
137 mar     (mar(ch)?)
138 apr     (apr(il)?)
139 may     (may)
140 jun     (jun(e)?)
141 jul     (jul(y)?)
142 aug     (aug(ust)?)
143 sep     (sep(tember)?)
144 oct     (oct(ober)?)
145 nov     (nov(ember)?)
146 dec     (dec(ember)?)
147
148 MONTH   ({jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec})
149
150 TIME    ({D}:{d}{d}(:{d}{d})?)
151
152 YEAR    (({d}{d})|(1{d}{d})|({d}{4}))
153
154 w       ([ \t]*)
155 W       ([ \t]+)
156 D       ([0-9]?[0-9])
157 d       [0-9]
158
159 %%
160 %{
161   
162   YY_BUFFER_STATE lexhandle;
163
164   register char *cp;  /* *cp is internal to the lexing function yylex() */
165   static struct tws tw; 
166
167   memset(&tw,0,sizeof(struct tws));
168   lexhandle = yy_scan_string(lexstr);
169 %}
170
171 {DAY}","?{W}{MONTH}{W}{D}{W}{TIME}{W}{YEAR} {
172                                      INIT();
173                                      SETWDAY();
174                                      SKIPTOA();
175                                      SETMON();
176                                      SKIPTOD();
177                                      SETDAY();
178                                      SKIPTOD();
179                                      SETTIME();
180                                      SKIPTOD();
181                                      SETYEAR();
182                                   }
183
184 {DAY}","?{W}{D}{W}{MONTH}{W}{YEAR}{W}{TIME}  {
185                                      INIT();
186                                      SETWDAY();
187                                      SKIPTOD();
188                                      SETDAY();
189                                      SKIPTOA();
190                                      SETMON();
191                                      SKIPTOD();
192                                      SETYEAR();
193                                      SKIPTOD();
194                                      SETTIME();
195                                   }
196 {D}{W}{MONTH}{W}{YEAR}{W}{TIME}         {
197                                      INIT();
198                                      SETDAY();
199                                      SKIPTOA();
200                                      SETMON();
201                                      SKIPTOD();
202                                      SETYEAR();
203                                      SKIPTOD();
204                                      SETTIME();
205                                   }
206 {DAY}","?{W}{MONTH}{W}{D}","?{W}{YEAR}","?{W}{TIME}  {
207                                      INIT();
208                                      SETWDAY();
209                                      SKIPTOA();
210                                      SETMON();
211                                      SKIPTOD();
212                                      SETDAY();
213                                      SKIPTOD();
214                                      SETYEAR();
215                                      SKIPTOD();
216                                      SETTIME();
217                                   }
218 {DAY}","?{W}{MONTH}{W}{D}","?{W}{YEAR}  {
219                                      INIT();
220                                      SETWDAY();
221                                      SKIPTOA();
222                                      SETMON();
223                                      SKIPTOD();
224                                      SETDAY();
225                                      SKIPTOD();
226                                      SETYEAR();
227                                   }
228 {MONTH}{W}{D}","?{W}{YEAR}","?{W}{DAY}     {
229                                      INIT();
230                                      SETMON();
231                                      SKIPTOD();
232                                      SETDAY();
233                                      SKIPTOD();
234                                      SETYEAR();
235                                      SKIPTOA();
236                                      SETWDAY();
237                                   }
238 {MONTH}{W}{D}","?{W}{YEAR}          {
239                                      INIT();
240                                      SETMON();
241                                      SKIPTOD();
242                                      SETDAY();
243                                      SKIPTOD();
244                                      SETYEAR();
245                                   }
246 {D}("-"|"/"){D}("-"|"/"){YEAR}{W}{TIME}     {
247                                      INIT();
248                                      if(europeandate) {
249                                        /* DD/MM/YY */
250                                      SETDAY();
251                                      SKIPTOD();
252                                      SETMON_NUM();
253                                      } else {
254                                        /* MM/DD/YY */
255                                      SETMON_NUM();
256                                      SKIPTOD();
257                                      SETDAY();
258                                      }
259                                      SKIPTOD();
260                                      SETYEAR();
261                                      SKIPTOD();
262                                      SETTIME();
263                                   }
264 {D}("-"|"/"){D}("-"|"/"){YEAR}     {
265                                      INIT();
266                                      if(europeandate) {
267                                        /* DD/MM/YY */
268                                      SETDAY();
269                                      SKIPTOD();
270                                      SETMON_NUM();
271                                      } else {
272                                        /* MM/DD/YY */
273                                      SETMON_NUM();
274                                      SKIPTOD();
275                                      SETDAY();
276                                      }
277                                      SKIPTOD();
278                                      SETYEAR();
279                                   }
280
281 "[Aa][Mm]" 
282 "[Pp][Mm]"                tw.tw_hour += 12;
283
284 "+"{D}{d}{d}              {
285                                     INIT();
286                                     SKIPTOD();
287                                     SETZONE(atoi(cp));
288                                 }
289 "-"{D}{d}{d}              {
290                                     INIT();
291                                     SKIPTOD();
292                                     SETZONE(-atoi(cp));
293                                 }
294 "-"?("ut"|"UT")                         INIT(); SETZONE(0);
295 "-"?("gmt"|"GMT")                       INIT(); SETZONE(0);
296 "-"?("jst"|"JST")                       INIT(); SETZONE(200);
297 "-"?("jdt"|"JDT")                       INIT(); SETDST(); SETZONE(2);
298 "-"?("est"|"EST")                       INIT(); SETZONE(-500);
299 "-"?("edt"|"EDT")                       INIT(); SETDST(); SETZONE(-500);
300 "-"?("cst"|"CST")                       INIT(); SETZONE(-600);
301 "-"?("cdt"|"CDT")                       INIT(); SETDST(); SETZONE(-600);
302 "-"?("mst"|"MST")                       INIT(); SETZONE(-700);
303 "-"?("mdt"|"MDT")                       INIT(); SETDST(); SETZONE(-700);
304 "-"?("pst"|"PST")                       INIT(); SETZONE(-800);
305 "-"?("pdt"|"PDT")                       INIT(); SETDST(); SETZONE(-800);
306 "-"?("nst"|"NST")                       INIT(); SETZONE(-330);
307 "-"?("ast"|"AST")                       INIT(); SETZONE(-400);
308 "-"?("adt"|"ADT")                       INIT(); SETDST(); SETZONE(-400);
309 "-"?("yst"|"YST")                       INIT(); SETZONE(-900);
310 "-"?("ydt"|"YDT")                       INIT(); SETDST(); SETZONE(-900);
311 "-"?("hst"|"HST")                       INIT(); SETZONE(-1000);
312 "-"?("hdt"|"HDT")                       INIT(); SETDST(); SETZONE(-1000);
313 "-"?("bst"|"BST")                       INIT(); SETDST(); SETZONE(-100);
314 [a-i]                   {
315                                        INIT();
316                                        SETZONE(100*(('a'-1) - tolower(*cp)));
317                         }
318 [k-m]                   {
319                                        INIT();
320                                        SETZONE(100*('a' - tolower(*cp)));
321                         }
322 [n-y]                   {
323                                        INIT();
324                                        SETZONE(100*(tolower(*cp) - 'm'));
325                         }
326
327
328 \n
329 .
330
331
332