14 DAY ({sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat})
29 MONTH ({jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec})
37 static char ident[] = "@(#)$Id: dtimep.lex,v 2.15 1993/02/26 22:07:40 jromine Exp $";
40 #include "../h/strings.h"
42 #include <sys/types.h>
43 #if !defined(SYS5) && !defined(ZONEINFO)
44 #include <sys/timeb.h>
45 #endif /* !defined(SYS5) && !defined(ZONEINFO) */
50 extern char *tzname[];
54 * Patchable flag that says how to interpret NN/NN/NN dates. When
55 * true, we do it European style: DD/MM/YY. When false, we do it
56 * American style: MM/DD/YY. Of course, these are all non-RFC822
62 * Table to convert month names to numeric month. We use the
63 * fact that the low order 5 bits of the sum of the 2nd & 3rd
64 * characters of the name is a hash with no collisions for the 12
65 * valid month names. (The mask to 5 bits maps any combination of
66 * upper and lower case into the same hash value).
68 static int month_map[] = {
100 * Same trick for day-of-week using the hash function
101 * (c1 & 7) + (c2 & 4)
103 static int day_map[] = {
117 #define SETDAY { tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)];\
118 tw.tw_flags &= ~TW_SDAY; tw.tw_flags |= TW_SEXP;\
120 #define SETMONTH { tw.tw_mon = month_map[(cp[0] + cp[1]) & 0x1f]; gotdate++;\
123 #define CVT1OR2 (i=(*cp++ - '0'), isdigit(*cp)? i*10 + (*cp++ - '0') : i)
124 #define CVT2 ((cp[0] - '0')*10 + (cp[1] - '0'))
125 #define CVT4 ((((cp[0] - '0')*10 + (cp[1] - '0'))*10 + \
126 (cp[2] - '0'))*10 + (cp[3] - '0'))
127 #define SKIPD { while ( !isdigit(*cp++) ) ; --cp; }
128 #define EXPZONE { tw.tw_flags &= ~TW_SZONE; tw.tw_flags |= TW_SZEXP; }
129 #define ZONE(x) { tw.tw_zone=(x); EXPZONE; }
130 #define ZONED(x) { ZONE(x); tw.tw_flags |= TW_DST; }
131 #define LC(c) (isupper (c) ? tolower (c) : (c))
135 #include <sys/time.h>
141 #include <sys/time.h>
146 register struct tws *tw;
148 register struct tm *tm;
150 if (twclock (tw) == -1L)
153 tm = localtime (&tw -> tw_clock);
154 if (tm -> tm_isdst) {
155 tw -> tw_flags |= TW_DST;
163 struct tws *dparsetime (str)
167 static struct tws tw;
169 register int gotdate = 0;
176 #endif /* ZONEINFO */
177 #endif /* not SYS5 */
182 /* Zero out the struct. */
183 bzero( (char *) &tw, sizeof tw);
185 /* Set default time zone. */
188 tw.tw_zone = -(timezone / 60);
192 tm = localtime(&clock);
193 tw.tw_zone = tm->tm_gmtoff / 60;
194 if (tm -> tm_isdst) /* if DST is in effect */
195 tw.tw_zone -= 60; /* reset to normal offset */
198 tw.tw_zone = -tb.timezone;
199 #endif /* ZONEINFO */
202 while (isspace(*str))
205 switch (cp = str, *cp ? lex_string( &str, start_cond) : 0) {
208 if (!gotdate || tw.tw_year == 0)
209 return (struct tws *)0;
212 if ( tw.tw_year == 0 ) {
213 /* Set default year. */
215 tw.tw_year = localtime(&tclock)->tm_year + 1900;
217 else if (tw.tw_year < 100) {
218 /* assume no 2-digit years > 1999 */
229 {D}(("-"{D}"-")|("/"{D}"/")){D}?{d}{d}{w} {
231 /* European: DD/MM/YY */
232 tw.tw_mday = CVT1OR2;
234 tw.tw_mon = CVT1OR2 - 1;
236 /* American: MM/DD/YY */
237 tw.tw_mon = CVT1OR2 - 1;
239 tw.tw_mday = CVT1OR2;
242 for (i = 0; isdigit(*cp); )
243 i = i*10 + (*cp++ - '0');
249 tw.tw_mday = CVT1OR2; cp++;
250 tw.tw_mon = CVT1OR2 - 1;
252 tw.tw_mon = CVT1OR2 - 1; cp++;
253 tw.tw_mday = CVT1OR2;
257 {D}{w}(-)?{w}{MONTH}{w}(-)?{w}{D}?{d}{d}({W}at)?{w} {
258 tw.tw_mday = CVT1OR2;
259 while ( !isalpha(*cp++) )
262 for (i = 0; isdigit(*cp); )
263 i = i*10 + (*cp++ - '0');
266 {D}"-"?{MONTH}({W}at)?{w} {
267 tw.tw_mday = CVT1OR2;
268 while ( ! isalpha( *cp++ ) )
272 {MONTH}{W}{D}","{W}{D}?{d}{d}{w} {
275 tw.tw_mday = CVT1OR2;
277 for (i = 0; isdigit(*cp); )
278 i = i*10 + (*cp++ - '0');
284 tw.tw_mday = CVT1OR2;
287 {D}:{D}:{D}{W}19[6-9]{d} { /* hack: ctime w/o TZ */
288 tw.tw_hour = CVT1OR2; cp++;
289 tw.tw_min = CVT1OR2; cp++;
292 tw.tw_year = CVT4; cp+=4;
295 tw.tw_hour = CVT1OR2; cp++;
296 tw.tw_min = CVT1OR2; cp++;
301 tw.tw_hour = CVT1OR2; cp++;
306 tw.tw_hour = CVT1OR2; cp++;
307 if (tw.tw_hour == 12)
312 {D}:{D}:{D}{w}am{w} {
313 tw.tw_hour = CVT1OR2; cp++;
314 if (tw.tw_hour == 12)
316 tw.tw_min = CVT1OR2; cp++;
321 tw.tw_hour = CVT1OR2; cp++;
322 if (tw.tw_hour != 12)
327 {D}:{D}:{D}{w}pm{w} {
328 tw.tw_hour = CVT1OR2; cp++;
329 if (tw.tw_hour != 12)
331 tw.tw_min = CVT1OR2; cp++;
335 [0-2]{d}{d}{d}{d}{d}{w} {
336 tw.tw_hour = CVT2; cp+=2;
337 tw.tw_min = CVT2; cp+=2;
338 tw.tw_sec = CVT2; cp+=2;
343 * Luckly, 4 digit times in the range
344 * 1960-1999 aren't legal as hour
347 tw.tw_year = CVT4; cp+=4;
350 if (tw.tw_hour || tw.tw_min
352 tw.tw_year = CVT4; cp+=4;
355 tw.tw_hour = CVT2; cp+=2;
356 tw.tw_min = CVT2; cp+=2;
360 <Z>"-"?ut ZONE(0 * 60);
361 <Z>"-"?gmt ZONE(0 * 60);
362 <Z>"-"?jst ZONE(2 * 60);
363 <Z>"-"?jdt ZONED(2 * 60);
364 <Z>"-"?est ZONE(-5 * 60);
365 <Z>"-"?edt ZONED(-5 * 60);
366 <Z>"-"?cst ZONE(-6 * 60);
367 <Z>"-"?cdt ZONED(-6 * 60);
368 <Z>"-"?mst ZONE(-7 * 60);
369 <Z>"-"?mdt ZONED(-7 * 60);
370 <Z>"-"?pst ZONE(-8 * 60);
371 <Z>"-"?pdt ZONED(-8 * 60);
372 <Z>"-"?nst ZONE(-(3 * 60 + 30));
373 <Z>"-"?ast ZONE(-4 * 60);
374 <Z>"-"?adt ZONED(-4 * 60);
375 <Z>"-"?yst ZONE(-9 * 60);
376 <Z>"-"?ydt ZONED(-9 * 60);
377 <Z>"-"?hst ZONE(-10 * 60);
378 <Z>"-"?hdt ZONED(-10 * 60);
379 <Z>"-"?bst ZONED(-1 * 60);
381 tw.tw_zone = 60 * (('a'-1) - LC(*cp));
385 tw.tw_zone = 60 * ('a' - LC(*cp));
389 tw.tw_zone = 60 * (LC(*cp) - 'm');
392 <Z>"+"[0-1]{d}{d}{d} {
394 tw.tw_zone = ((cp[0] * 10 + cp[1])
395 -('0' * 10 + '0'))*60
396 +((cp[2] * 10 + cp[3])
404 <Z>"-"[0-1]{d}{d}{d} {
406 tw.tw_zone = (('0' * 10 + '0')
407 -(cp[0] * 10 + cp[1]))*60
409 -(cp[2] * 10 + cp[3]));
418 tw.tw_year = CVT4; cp+=4;