]> diplodocus.org Git - nmh/blob - zotnet/tws/dtimep.lex
Put in a prototype for client() to get rid of the "default prototype" warning.
[nmh] / zotnet / tws / dtimep.lex
1 %e 2000
2 %p 5000
3 %n 1000
4 %a 4000
5 %START Z
6 sun (sun(day)?)
7 mon (mon(day)?)
8 tue (tue(sday)?)
9 wed (wed(nesday)?)
10 thu (thu(rsday)?)
11 fri (fri(day)?)
12 sat (sat(urday)?)
13
14 DAY ({sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat})
15
16 jan (jan(uary)?)
17 feb (feb(ruary)?)
18 mar (mar(ch)?)
19 apr (apr(il)?)
20 may (may)
21 jun (jun(e)?)
22 jul (jul(y)?)
23 aug (aug(ust)?)
24 sep (sep(tember)?)
25 oct (oct(ober)?)
26 nov (nov(ember)?)
27 dec (dec(ember)?)
28
29 MONTH ({jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec})
30
31 w ([ \t]*)
32 W ([ \t]+)
33 D ([0-9]?[0-9])
34 d [0-9]
35 %{
36 #include <h/nmh.h>
37 #include <tws.h>
38 #if !defined(HAVE_TM_GMTOFF) && !defined(HAVE_TZSET)
39 # include <sys/timeb.h>
40 #endif
41
42 #if !defined(HAVE_TM_GMTOFF) && defined(HAVE_TZSET)
43 extern int daylight;
44 extern long timezone;
45 extern char *tzname[];
46 #endif
47
48 /*
49 * Patchable flag that says how to interpret NN/NN/NN dates. When
50 * true, we do it European style: DD/MM/YY. When false, we do it
51 * American style: MM/DD/YY. Of course, these are all non-RFC822
52 * compliant.
53 */
54 int europeandate = 0;
55
56 /*
57 * Table to convert month names to numeric month. We use the
58 * fact that the low order 5 bits of the sum of the 2nd & 3rd
59 * characters of the name is a hash with no collisions for the 12
60 * valid month names. (The mask to 5 bits maps any combination of
61 * upper and lower case into the same hash value).
62 */
63 static int month_map[] = {
64 0,
65 6, /* 1 - Jul */
66 3, /* 2 - Apr */
67 5, /* 3 - Jun */
68 0,
69 10, /* 5 - Nov */
70 0,
71 1, /* 7 - Feb */
72 11, /* 8 - Dec */
73 0,
74 0,
75 0,
76 0,
77 0,
78 0,
79 0, /*15 - Jan */
80 0,
81 0,
82 0,
83 2, /*19 - Mar */
84 0,
85 8, /*21 - Sep */
86 0,
87 9, /*23 - Oct */
88 0,
89 0,
90 4, /*26 - May */
91 0,
92 7 /*28 - Aug */
93 };
94 /*
95 * Same trick for day-of-week using the hash function
96 * (c1 & 7) + (c2 & 4)
97 */
98 static int day_map[] = {
99 0,
100 0,
101 0,
102 6, /* 3 - Sat */
103 4, /* 4 - Thu */
104 0,
105 5, /* 6 - Fri */
106 0, /* 7 - Sun */
107 2, /* 8 - Tue */
108 1 /* 9 - Mon */,
109 0,
110 3 /*11 - Wed */
111 };
112 #define SETDAY { tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)];\
113 tw.tw_flags &= ~TW_SDAY; tw.tw_flags |= TW_SEXP;\
114 cp += 2; }
115 #define SETMONTH { tw.tw_mon = month_map[(cp[0] + cp[1]) & 0x1f]; gotdate++;\
116 cp += 2;\
117 SKIPD;}
118 #define CVT1OR2 (i=(*cp++ - '0'), isdigit(*cp)? i*10 + (*cp++ - '0') : i)
119 #define CVT2 ((cp[0] - '0')*10 + (cp[1] - '0'))
120 #define CVT4 ((((cp[0] - '0')*10 + (cp[1] - '0'))*10 + \
121 (cp[2] - '0'))*10 + (cp[3] - '0'))
122 #define SKIPD { while ( !isdigit(*cp++) ) ; --cp; }
123 #define EXPZONE { tw.tw_flags &= ~TW_SZONE; tw.tw_flags |= TW_SZEXP; }
124 #define ZONE(x) { tw.tw_zone=(x); EXPZONE; }
125 #define ZONED(x) { ZONE(x); tw.tw_flags |= TW_DST; }
126 #define LC(c) (isupper (c) ? tolower (c) : (c))
127
128 #ifdef DSTXXX
129 # ifdef TIME_WITH_SYS_TIME
130 # include <sys/time.h>
131 # include <time.h>
132 # else
133 # ifdef HAVE_SYS_TIME_H
134 # include <sys/time.h>
135 # else
136 # include <time.h>
137 # endif
138 # endif
139
140 static void
141 zonehack (struct tws *tw)
142 {
143 register struct tm *tm;
144
145 if (dmktime (tw) == (time_t) -1)
146 return;
147
148 tm = localtime (&tw->tw_clock);
149 if (tm->tm_isdst) {
150 tw->tw_flags |= TW_DST;
151 tw->tw_zone -= 60;
152 }
153 }
154 #endif /* DSTXXX */
155 %}
156 %%
157 %{
158 struct tws *
159 dparsetime (char *str)
160 {
161 register int i;
162 static struct tws tw;
163 register char *cp;
164 register int gotdate = 0;
165 time_t tclock;
166
167 #ifdef HAVE_TM_GMTOFF
168 struct tm *tm;
169 time_t clock;
170 #else
171 # ifndef HAVE_TZSET
172 struct timeb tb;
173 # endif /* not HAVE_TZSET */
174 #endif /* HAVE_TM_GMTOFF */
175
176 start_cond = 0;
177
178 /* Zero out the struct. */
179 memset( (char *) &tw, 0, sizeof(tw));
180
181 /* Set default time zone. */
182 #ifdef HAVE_TM_GMTOFF
183 time (&clock);
184 tm = localtime(&clock);
185 tw.tw_zone = tm->tm_gmtoff / 60;
186 if (tm->tm_isdst) /* if DST is in effect */
187 tw.tw_zone -= 60; /* reset to normal offset */
188 #else
189 # ifdef HAVE_TZSET
190 tzset();
191 tw.tw_zone = -(timezone / 60);
192 # else
193 ftime(&tb);
194 tw.tw_zone = -tb.timezone;
195 # endif /* HAVE_TZSET */
196 #endif /* HAVE_TM_GMTOFF */
197
198 while (isspace(*str))
199 str++;
200 while (1)
201 switch (cp = str, *cp ? lex_string( &str, start_cond) : 0) {
202
203 case -1:
204 if (!gotdate || tw.tw_year == 0)
205 return (struct tws *)0;
206 /* fall through */
207 case 0:
208 if (tw.tw_year == 0) {
209 /* Set default year. */
210 time (&tclock);
211 tw.tw_year = localtime(&tclock)->tm_year + 1900;
212 } else if (tw.tw_year < 100) {
213 /* assume no 2-digit years > 1999 */
214 tw.tw_year += 1900;
215 }
216 return &tw;
217
218 %}
219 {DAY}","?{w} SETDAY;
220 "("{DAY}")"(","?) {
221 cp++;
222 SETDAY;
223 }
224 {D}(("-"{D}"-")|("/"{D}"/")){D}?{d}{d}{w} {
225 if (europeandate) {
226 /* European: DD/MM/YY */
227 tw.tw_mday = CVT1OR2;
228 cp++;
229 tw.tw_mon = CVT1OR2 - 1;
230 } else {
231 /* American: MM/DD/YY */
232 tw.tw_mon = CVT1OR2 - 1;
233 cp++;
234 tw.tw_mday = CVT1OR2;
235 }
236 cp++;
237 for (i = 0; isdigit(*cp); )
238 i = i*10 + (*cp++ - '0');
239 tw.tw_year = i;
240 gotdate++; /* XXX */
241 }
242 {D}("/"|"-"){D}{w} {
243 if (europeandate) {
244 tw.tw_mday = CVT1OR2; cp++;
245 tw.tw_mon = CVT1OR2 - 1;
246 } else {
247 tw.tw_mon = CVT1OR2 - 1; cp++;
248 tw.tw_mday = CVT1OR2;
249 }
250 gotdate++;
251 }
252 {D}{w}(-)?{w}{MONTH}{w}(-)?{w}{D}?{d}{d}({W}at)?{w} {
253 tw.tw_mday = CVT1OR2;
254 while ( !isalpha(*cp++) )
255 ;
256 SETMONTH;
257 for (i = 0; isdigit(*cp); )
258 i = i*10 + (*cp++ - '0');
259 tw.tw_year = i;
260 }
261 {D}"-"?{MONTH}({W}at)?{w} {
262 tw.tw_mday = CVT1OR2;
263 while ( ! isalpha( *cp++ ) )
264 ;
265 SETMONTH;
266 }
267 {MONTH}{W}{D}","{W}{D}?{d}{d}{w} {
268 cp++;
269 SETMONTH;
270 tw.tw_mday = CVT1OR2;
271 SKIPD;
272 for (i = 0; isdigit(*cp); )
273 i = i*10 + (*cp++ - '0');
274 tw.tw_year = i;
275 }
276 {MONTH}{W}{D}{w} {
277 cp++;
278 SETMONTH;
279 tw.tw_mday = CVT1OR2;
280 }
281
282 {D}:{D}:{D}{W}19[6-9]{d} { /* hack: ctime w/o TZ */
283 tw.tw_hour = CVT1OR2; cp++;
284 tw.tw_min = CVT1OR2; cp++;
285 tw.tw_sec = CVT1OR2;
286 SKIPD;
287 tw.tw_year = CVT4; cp+=4;
288 }
289 {D}:{D}:{D}{w} {
290 tw.tw_hour = CVT1OR2; cp++;
291 tw.tw_min = CVT1OR2; cp++;
292 tw.tw_sec = CVT1OR2;
293 BEGIN Z;
294 }
295 {D}:{D}{w} {
296 tw.tw_hour = CVT1OR2; cp++;
297 tw.tw_min = CVT1OR2;
298 BEGIN Z;
299 }
300 {D}:{D}{w}am{w} {
301 tw.tw_hour = CVT1OR2; cp++;
302 if (tw.tw_hour == 12)
303 tw.tw_hour = 0;
304 tw.tw_min = CVT1OR2;
305 BEGIN Z;
306 }
307 {D}:{D}:{D}{w}am{w} {
308 tw.tw_hour = CVT1OR2; cp++;
309 if (tw.tw_hour == 12)
310 tw.tw_hour = 0;
311 tw.tw_min = CVT1OR2; cp++;
312 tw.tw_sec = CVT1OR2;
313 BEGIN Z;
314 }
315 {D}:{D}{w}pm{w} {
316 tw.tw_hour = CVT1OR2; cp++;
317 if (tw.tw_hour != 12)
318 tw.tw_hour += 12;
319 tw.tw_min = CVT1OR2;
320 BEGIN Z;
321 }
322 {D}:{D}:{D}{w}pm{w} {
323 tw.tw_hour = CVT1OR2; cp++;
324 if (tw.tw_hour != 12)
325 tw.tw_hour += 12;
326 tw.tw_min = CVT1OR2; cp++;
327 tw.tw_sec = CVT1OR2;
328 BEGIN Z;
329 }
330 [0-2]{d}{d}{d}{d}{d}{w} {
331 tw.tw_hour = CVT2; cp+=2;
332 tw.tw_min = CVT2; cp+=2;
333 tw.tw_sec = CVT2; cp+=2;
334 BEGIN Z;
335 }
336 19[6-9]{d}{w} {
337 /*
338 * Luckly, 4 digit times in the range
339 * 1960-1999 aren't legal as hour
340 * and minutes.
341 */
342 tw.tw_year = CVT4; cp+=4;
343 }
344 [0-2]{d}{d}{d}{w} {
345 if (tw.tw_hour || tw.tw_min
346 || tw.tw_sec) {
347 tw.tw_year = CVT4; cp+=4;
348 tw.tw_zone = 0;
349 } else {
350 tw.tw_hour = CVT2; cp+=2;
351 tw.tw_min = CVT2; cp+=2;
352 BEGIN Z;
353 }
354 }
355 <Z>"-"?ut ZONE(0 * 60);
356 <Z>"-"?gmt ZONE(0 * 60);
357 <Z>"-"?jst ZONE(2 * 60);
358 <Z>"-"?jdt ZONED(2 * 60);
359 <Z>"-"?est ZONE(-5 * 60);
360 <Z>"-"?edt ZONED(-5 * 60);
361 <Z>"-"?cst ZONE(-6 * 60);
362 <Z>"-"?cdt ZONED(-6 * 60);
363 <Z>"-"?mst ZONE(-7 * 60);
364 <Z>"-"?mdt ZONED(-7 * 60);
365 <Z>"-"?pst ZONE(-8 * 60);
366 <Z>"-"?pdt ZONED(-8 * 60);
367 <Z>"-"?nst ZONE(-(3 * 60 + 30));
368 <Z>"-"?ast ZONE(-4 * 60);
369 <Z>"-"?adt ZONED(-4 * 60);
370 <Z>"-"?yst ZONE(-9 * 60);
371 <Z>"-"?ydt ZONED(-9 * 60);
372 <Z>"-"?hst ZONE(-10 * 60);
373 <Z>"-"?hdt ZONED(-10 * 60);
374 <Z>"-"?bst ZONED(-1 * 60);
375 <Z>[a-i] {
376 tw.tw_zone = 60 * (('a'-1) - LC(*cp));
377 EXPZONE;
378 }
379 <Z>[k-m] {
380 tw.tw_zone = 60 * ('a' - LC(*cp));
381 EXPZONE;
382 }
383 <Z>[n-y] {
384 tw.tw_zone = 60 * (LC(*cp) - 'm');
385 EXPZONE;
386 }
387 <Z>"+"[0-1]{d}{d}{d} {
388 cp++;
389 tw.tw_zone = ((cp[0] * 10 + cp[1])
390 -('0' * 10 + '0'))*60
391 +((cp[2] * 10 + cp[3])
392 -('0' * 10 + '0'));
393 EXPZONE;
394 #ifdef DSTXXX
395 zonehack (&tw);
396 #endif /* DSTXXX */
397 cp += 4;
398 }
399 <Z>"-"[0-1]{d}{d}{d} {
400 cp++;
401 tw.tw_zone = (('0' * 10 + '0')
402 -(cp[0] * 10 + cp[1]))*60
403 +(('0' * 10 + '0')
404 -(cp[2] * 10 + cp[3]));
405 EXPZONE;
406 #ifdef DSTXXX
407 zonehack (&tw);
408 #endif /* DSTXXX */
409 cp += 4;
410 }
411 <Z>{W}{d}{d}{d}{d} {
412 SKIPD;
413 tw.tw_year = CVT4; cp+=4;
414 }
415 \n |
416 {W} ;
417 %%