]> git.zerfleddert.de Git - micropolis/blob - src/tclx/src/tclxgdat.y
e29d7ead98a87d8a48e49c2edbed0248e937eef9
[micropolis] / src / tclx / src / tclxgdat.y
1 /*
2 * tclXgetdate.y --
3 *
4 * Contains yacc grammer for parsing date and time strings..
5 *---------------------------------------------------------------------------
6 * Copyright 1992 Karl Lehenbauer and Mark Diekhans.
7 *
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation for any purpose and without fee is hereby granted, provided
10 * that the above copyright notice appear in all copies. Karl Lehenbauer and
11 * Mark Diekhans make no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *---------------------------------------------------------------------------
15 * This code is a slightly modified version of getdate.y by:
16 * Steven M. Bellovin (unc!smb)
17 * Dept. of Computer Science
18 * University of North Carolina at Chapel Hill
19 * getdate.y 2.13 9/16/86
20 *-----------------------------------------------------------------------------
21 * $Id: tclXgetdate.y,v 2.0 1992/10/16 04:51:34 markd Rel $
22 *-----------------------------------------------------------------------------
23 */
24
25 %token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
26 %{
27 #include <unistd.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <ctype.h>
31 #include <time.h>
32
33 #ifndef NULL
34 # define NULL 0
35 #endif
36
37 #define daysec (24L*60L*60L)
38
39 static int timeflag, zoneflag, dateflag, dayflag, relflag;
40 static time_t relsec, relmonth;
41 static int hh, mm, ss, merid, dayLight;
42 static int dayord, dayreq;
43 static int month, day, year;
44 static int ourzone;
45
46 #if 0
47 static time_t timeconv(int hh, int mm, int ss, int mer);
48 static time_t daylcorr(time_t future, time_t now);
49 static lookup(char *id);
50 #else
51 static time_t timeconv();
52 static time_t daylcorr();
53 static lookup();
54 #endif
55
56 #define AM 1
57 #define PM 2
58 #define DAYLIGHT 1
59 #define STANDARD 2
60 #define MAYBE 3
61 %}
62
63 %%
64 timedate: /* empty */
65 | timedate item;
66
67 item: tspec
68 {timeflag++;}
69 | zone
70 {zoneflag++;}
71 | dtspec
72 {dateflag++;}
73 | dyspec
74 {dayflag++;}
75 | rspec
76 {relflag++;}
77 | nspec;
78
79 nspec: NUMBER
80 {if (timeflag && dateflag && !relflag) year = $1;
81 else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
82
83 tspec: NUMBER MERIDIAN
84 {hh = $1; mm = 0; ss = 0; merid = $2;}
85 | NUMBER ':' NUMBER
86 {hh = $1; mm = $3; merid = 24;}
87 | NUMBER ':' NUMBER MERIDIAN
88 {hh = $1; mm = $3; merid = $4;}
89 | NUMBER ':' NUMBER NUMBER
90 {hh = $1; mm = $3; merid = 24;
91 dayLight = STANDARD; ourzone = -($4%100 + 60*$4/100);}
92 | NUMBER ':' NUMBER ':' NUMBER
93 {hh = $1; mm = $3; ss = $5; merid = 24;}
94 | NUMBER ':' NUMBER ':' NUMBER MERIDIAN
95 {hh = $1; mm = $3; ss = $5; merid = $6;}
96 | NUMBER ':' NUMBER ':' NUMBER NUMBER
97 {hh = $1; mm = $3; ss = $5; merid = 24;
98 dayLight = STANDARD; ourzone = -($6%100 + 60*$6/100);};
99
100 zone: ZONE
101 {ourzone = $1; dayLight = STANDARD;}
102 | DAYZONE
103 {ourzone = $1; dayLight = DAYLIGHT;};
104
105 dyspec: DAY
106 {dayord = 1; dayreq = $1;}
107 | DAY ','
108 {dayord = 1; dayreq = $1;}
109 | NUMBER DAY
110 {dayord = $1; dayreq = $2;};
111
112 dtspec: NUMBER '/' NUMBER
113 {month = $1; day = $3;}
114 | NUMBER '/' NUMBER '/' NUMBER
115 {month = $1; day = $3; year = $5;}
116 | MONTH NUMBER
117 {month = $1; day = $2;}
118 | MONTH NUMBER ',' NUMBER
119 {month = $1; day = $2; year = $4;}
120 | NUMBER MONTH
121 {month = $2; day = $1;}
122 | NUMBER MONTH NUMBER
123 {month = $2; day = $1; year = $3;};
124
125
126 rspec: NUMBER UNIT
127 {relsec += 60L * $1 * $2;}
128 | NUMBER MUNIT
129 {relmonth += $1 * $2;}
130 | NUMBER SUNIT
131 {relsec += $1;}
132 | UNIT
133 {relsec += 60L * $1;}
134 | MUNIT
135 {relmonth += $1;}
136 | SUNIT
137 {relsec++;}
138 | rspec AGO
139 {relsec = -relsec; relmonth = -relmonth;};
140 %%
141
142 static int mdays[12] =
143 {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
144 #define epoch 1970
145
146 extern struct tm *localtime();
147
148 static
149 time_t dateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
150 int mm, dd, yy, h, m, s, mer, zone, dayflag;
151 {
152 time_t tod, jdate;
153 register int i;
154 time_t timeconv();
155
156 if (yy < 0) yy = -yy;
157 if (yy < 100) yy += 1900;
158 mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0));
159 if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
160 dd < 1 || dd > mdays[--mm]) return (-1);
161 jdate = dd-1;
162 for (i=0; i<mm; i++) jdate += mdays[i];
163 for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
164 jdate *= daysec;
165 jdate += zone * 60L;
166 if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
167 jdate += tod;
168 if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
169 jdate += -1*60*60;
170 return (jdate);
171 }
172
173 static
174 time_t dayconv(ord, day, now) int ord, day; time_t now;
175 {
176 register struct tm *loctime;
177 time_t tod;
178 time_t daylcorr();
179
180 tod = now;
181 loctime = localtime(&tod);
182 tod += daysec * ((day - loctime->tm_wday + 7) % 7);
183 tod += 7*daysec*(ord<=0?ord:ord-1);
184 return daylcorr(tod, now);
185 }
186
187 static
188 time_t timeconv(hh, mm, ss, mer) register int hh, mm, ss, mer;
189 {
190 if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
191 switch (mer) {
192 case AM: if (hh < 1 || hh > 12) return(-1);
193 return (60L * ((hh%12)*60L + mm)+ss);
194 case PM: if (hh < 1 || hh > 12) return(-1);
195 return (60L * ((hh%12 +12)*60L + mm)+ss);
196 case 24: if (hh < 0 || hh > 23) return (-1);
197 return (60L * (hh*60L + mm)+ss);
198 default: return (-1);
199 }
200 }
201
202 static
203 time_t monthadd(sdate, relmonth) time_t sdate, relmonth;
204 {
205 struct tm *ltime;
206 time_t dateconv();
207 time_t daylcorr();
208 int mm, yy;
209
210 if (relmonth == 0) return 0;
211 ltime = localtime(&sdate);
212 mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
213 yy = mm/12;
214 mm = mm%12 + 1;
215 return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
216 ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
217 }
218
219 static
220 time_t daylcorr(future, now) time_t future, now;
221 {
222 int fdayl, nowdayl;
223
224 nowdayl = (localtime(&now)->tm_hour+1) % 24;
225 fdayl = (localtime(&future)->tm_hour+1) % 24;
226 return (future-now) + 60L*60L*(nowdayl-fdayl);
227 }
228
229 static char *lptr;
230
231 //static
232 yylex()
233 {
234 #ifndef YYSTYPE
235 //#define YYSTYPE extern int
236 #define YYSTYPE int
237 #endif
238 YYSTYPE yylval;
239 int sign;
240 register char c;
241 register char *p;
242 char idbuf[20];
243 int pcnt;
244
245 for (;;) {
246 while (isspace(*lptr)) lptr++;
247
248 if (isdigit(c = *lptr) || c == '-' || c == '+') {
249 if (c== '-' || c == '+') {
250 if (c=='-') sign = -1;
251 else sign = 1;
252 if (!isdigit(*++lptr)) {
253 /* yylval = sign; return (NUMBER); */
254 return yylex(); /* skip the '-' sign */
255 }
256 } else sign = 1;
257 yylval = 0;
258 while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
259 yylval *= sign;
260 lptr--;
261 return (NUMBER);
262
263 } else if (isalpha(c)) {
264 p = idbuf;
265 while (isalpha(c = *lptr++) || c=='.')
266 if (p < &idbuf[sizeof(idbuf)-1])
267 *p++ = c;
268 *p = '\0';
269 lptr--;
270 return (lookup(idbuf));
271 }
272
273 else if (c == '(') {
274 pcnt = 0;
275 do {
276 c = *lptr++;
277 if (c == '\0') return(c);
278 else if (c == '(') pcnt++;
279 else if (c == ')') pcnt--;
280 } while (pcnt > 0);
281 }
282
283 else return (*lptr++);
284 }
285 }
286
287 //static
288 struct table {
289 char *name;
290 int type, value;
291 };
292
293 static
294 struct table mdtab[] = {
295 {"January", MONTH, 1},
296 {"February", MONTH, 2},
297 {"March", MONTH, 3},
298 {"April", MONTH, 4},
299 {"May", MONTH, 5},
300 {"June", MONTH, 6},
301 {"July", MONTH, 7},
302 {"August", MONTH, 8},
303 {"September", MONTH, 9},
304 {"Sept", MONTH, 9},
305 {"October", MONTH, 10},
306 {"November", MONTH, 11},
307 {"December", MONTH, 12},
308
309 {"Sunday", DAY, 0},
310 {"Monday", DAY, 1},
311 {"Tuesday", DAY, 2},
312 {"Tues", DAY, 2},
313 {"Wednesday", DAY, 3},
314 {"Wednes", DAY, 3},
315 {"Thursday", DAY, 4},
316 {"Thur", DAY, 4},
317 {"Thurs", DAY, 4},
318 {"Friday", DAY, 5},
319 {"Saturday", DAY, 6},
320 {0, 0, 0}};
321
322 #define HRS *60
323 #define HALFHR 30
324 static
325 struct table mztab[] = {
326 {"a.m.", MERIDIAN, AM},
327 {"am", MERIDIAN, AM},
328 {"p.m.", MERIDIAN, PM},
329 {"pm", MERIDIAN, PM},
330 {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
331 {"n.s.t.", ZONE, 3 HRS + HALFHR},
332 {"ast", ZONE, 4 HRS}, /* Atlantic */
333 {"a.s.t.", ZONE, 4 HRS},
334 {"adt", DAYZONE, 4 HRS},
335 {"a.d.t.", DAYZONE, 4 HRS},
336 {"est", ZONE, 5 HRS}, /* Eastern */
337 {"e.s.t.", ZONE, 5 HRS},
338 {"edt", DAYZONE, 5 HRS},
339 {"e.d.t.", DAYZONE, 5 HRS},
340 {"cst", ZONE, 6 HRS}, /* Central */
341 {"c.s.t.", ZONE, 6 HRS},
342 {"cdt", DAYZONE, 6 HRS},
343 {"c.d.t.", DAYZONE, 6 HRS},
344 {"mst", ZONE, 7 HRS}, /* Mountain */
345 {"m.s.t.", ZONE, 7 HRS},
346 {"mdt", DAYZONE, 7 HRS},
347 {"m.d.t.", DAYZONE, 7 HRS},
348 {"pst", ZONE, 8 HRS}, /* Pacific */
349 {"p.s.t.", ZONE, 8 HRS},
350 {"pdt", DAYZONE, 8 HRS},
351 {"p.d.t.", DAYZONE, 8 HRS},
352 {"yst", ZONE, 9 HRS}, /* Yukon */
353 {"y.s.t.", ZONE, 9 HRS},
354 {"ydt", DAYZONE, 9 HRS},
355 {"y.d.t.", DAYZONE, 9 HRS},
356 {"hst", ZONE, 10 HRS}, /* Hawaii */
357 {"h.s.t.", ZONE, 10 HRS},
358 {"hdt", DAYZONE, 10 HRS},
359 {"h.d.t.", DAYZONE, 10 HRS},
360
361 {"gmt", ZONE, 0 HRS},
362 {"g.m.t.", ZONE, 0 HRS},
363 {"bst", DAYZONE, 0 HRS}, /* British Summer Time */
364 {"b.s.t.", DAYZONE, 0 HRS},
365 {"eet", ZONE, 0 HRS}, /* European Eastern Time */
366 {"e.e.t.", ZONE, 0 HRS},
367 {"eest", DAYZONE, 0 HRS}, /* European Eastern Summer Time */
368 {"e.e.s.t.", DAYZONE, 0 HRS},
369 {"met", ZONE, -1 HRS}, /* Middle European Time */
370 {"m.e.t.", ZONE, -1 HRS},
371 {"mest", DAYZONE, -1 HRS}, /* Middle European Summer Time */
372 {"m.e.s.t.", DAYZONE, -1 HRS},
373 {"wet", ZONE, -2 HRS }, /* Western European Time */
374 {"w.e.t.", ZONE, -2 HRS },
375 {"west", DAYZONE, -2 HRS}, /* Western European Summer Time */
376 {"w.e.s.t.", DAYZONE, -2 HRS},
377
378 {"jst", ZONE, -9 HRS}, /* Japan Standard Time */
379 {"j.s.t.", ZONE, -9 HRS}, /* Japan Standard Time */
380 /* No daylight savings time */
381
382 {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
383 {"a.e.s.t.", ZONE, -10 HRS},
384 {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
385 {"a.e.s.s.t.", DAYZONE, -10 HRS},
386 {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
387 {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
388 {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
389 {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
390 {"awst", ZONE, -8 HRS}, /* Australian Western Time */
391 {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylight time there, I'm told */
392 {0, 0, 0}};
393
394 static
395 struct table unittb[] = {
396 {"year", MUNIT, 12},
397 {"month", MUNIT, 1},
398 {"fortnight", UNIT, 14*24*60},
399 {"week", UNIT, 7*24*60},
400 {"day", UNIT, 1*24*60},
401 {"hour", UNIT, 60},
402 {"minute", UNIT, 1},
403 {"min", UNIT, 1},
404 {"second", SUNIT, 1},
405 {"sec", SUNIT, 1},
406 {0, 0, 0}};
407
408 static
409 struct table othertb[] = {
410 {"tomorrow", UNIT, 1*24*60},
411 {"yesterday", UNIT, -1*24*60},
412 {"today", UNIT, 0},
413 {"now", UNIT, 0},
414 {"last", NUMBER, -1},
415 {"this", UNIT, 0},
416 {"next", NUMBER, 2},
417 {"first", NUMBER, 1},
418 /* {"second", NUMBER, 2}, */
419 {"third", NUMBER, 3},
420 {"fourth", NUMBER, 4},
421 {"fifth", NUMBER, 5},
422 {"sixth", NUMBER, 6},
423 {"seventh", NUMBER, 7},
424 {"eigth", NUMBER, 8},
425 {"ninth", NUMBER, 9},
426 {"tenth", NUMBER, 10},
427 {"eleventh", NUMBER, 11},
428 {"twelfth", NUMBER, 12},
429 {"ago", AGO, 1},
430 {0, 0, 0}};
431
432 static
433 struct table milzone[] = {
434 {"a", ZONE, 1 HRS},
435 {"b", ZONE, 2 HRS},
436 {"c", ZONE, 3 HRS},
437 {"d", ZONE, 4 HRS},
438 {"e", ZONE, 5 HRS},
439 {"f", ZONE, 6 HRS},
440 {"g", ZONE, 7 HRS},
441 {"h", ZONE, 8 HRS},
442 {"i", ZONE, 9 HRS},
443 {"k", ZONE, 10 HRS},
444 {"l", ZONE, 11 HRS},
445 {"m", ZONE, 12 HRS},
446 {"n", ZONE, -1 HRS},
447 {"o", ZONE, -2 HRS},
448 {"p", ZONE, -3 HRS},
449 {"q", ZONE, -4 HRS},
450 {"r", ZONE, -5 HRS},
451 {"s", ZONE, -6 HRS},
452 {"t", ZONE, -7 HRS},
453 {"u", ZONE, -8 HRS},
454 {"v", ZONE, -9 HRS},
455 {"w", ZONE, -10 HRS},
456 {"x", ZONE, -11 HRS},
457 {"y", ZONE, -12 HRS},
458 {"z", ZONE, 0 HRS},
459 {0, 0, 0}};
460
461 static
462 lookup(id) char *id;
463 {
464 #define gotit (yylval=i->value, i->type)
465 #define getid for(j=idvar, k=id; *j++ = *k++; )
466
467 char idvar[20];
468 register char *j, *k;
469 register struct table *i;
470 int abbrev;
471
472 getid;
473 if (strlen(idvar) == 3) abbrev = 1;
474 else if (strlen(idvar) == 4 && idvar[3] == '.') {
475 abbrev = 1;
476 idvar[3] = '\0';
477 }
478 else abbrev = 0;
479
480 if (islower(*idvar)) *idvar = toupper(*idvar);
481
482 for (i = mdtab; i->name; i++) {
483 k = idvar;
484 for (j = i->name; *j++ == *k++;) {
485 if (abbrev && j==i->name+3) return gotit;
486 if (j[-1] == 0) return gotit;
487 }
488 }
489
490 getid;
491 for (i = mztab; i->name; i++)
492 if (strcmp(i->name, idvar) == 0) return gotit;
493
494 for (j = idvar; *j; j++)
495 if (isupper(*j)) *j = tolower(*j);
496 for (i=mztab; i->name; i++)
497 if (strcmp(i->name, idvar) == 0) return gotit;
498
499 getid;
500 for (i=unittb; i->name; i++)
501 if (strcmp(i->name, idvar) == 0) return gotit;
502
503 if (idvar[strlen(idvar)-1] == 's')
504 idvar[strlen(idvar)-1] = '\0';
505 for (i=unittb; i->name; i++)
506 if (strcmp(i->name, idvar) == 0) return gotit;
507
508 getid;
509 for (i = othertb; i->name; i++)
510 if (strcmp(i->name, idvar) == 0) return gotit;
511
512 getid;
513 if (strlen(idvar) == 1 && isalpha(*idvar)) {
514 if (isupper(*idvar)) *idvar = tolower(*idvar);
515 for (i = milzone; i->name; i++)
516 if (strcmp(i->name, idvar) == 0) return gotit;
517 }
518
519 return(ID);
520 }
521
522 time_t
523 Tcl_GetDate (p, now, zone)
524 char *p;
525 time_t now;
526 long zone;
527 {
528 #define mcheck(f) if (f>1) err++
529 time_t monthadd();
530 int err;
531 struct tm *lt;
532 time_t sdate, tod;
533
534 lptr = p;
535 if (now <= 0)
536 (void) time(&now);
537 lt = localtime(&now);
538 year = lt->tm_year;
539 month = lt->tm_mon+1;
540 day = lt->tm_mday;
541 relsec = 0; relmonth = 0;
542 timeflag=zoneflag=dateflag=dayflag=relflag=0;
543 dayLight = MAYBE;
544 hh = mm = ss = 0;
545 merid = 24;
546 ourzone = zone;
547
548 if (err = yyparse()) return (-1);
549
550 mcheck(timeflag);
551 mcheck(zoneflag);
552 mcheck(dateflag);
553 mcheck(dayflag);
554
555 if (err) return (-1);
556 if (dateflag || timeflag || dayflag) {
557 sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,
558 dayLight);
559 if (sdate < 0) return -1;
560 }
561 else {
562 sdate = now;
563 if (relflag == 0)
564 sdate -= (lt->tm_sec + lt->tm_min*60 +
565 lt->tm_hour*(60L*60L));
566 }
567
568 sdate += relsec;
569 sdate += monthadd(sdate, relmonth);
570
571 if (dayflag && !dateflag) {
572 tod = dayconv(dayord, dayreq, sdate);
573 sdate += tod;
574 }
575
576 return sdate;
577 }
578
579 /*
580 * Error message are not used, so discard with dummy function.
581 */
582
583 void
584 yyerror(msg)
585 char *msg;
586 {
587 }
Impressum, Datenschutz