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