os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclGetDate.y
First public contribution.
4 * Contains yacc grammar for parsing date and time strings.
5 * The output of this file should be the file tclDate.c which
6 * is used directly in the Tcl sources.
8 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
9 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * RCS: @(#) $Id: tclGetDate.y,v 1.18.4.2 2005/11/04 20:15:09 kennykb Exp $
21 * This file is generated from a yacc grammar defined in
22 * the file tclGetDate.y. It should not be edited directly.
24 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
25 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
27 * See the file "license.terms" for information on usage and redistribution
28 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
36 #if defined(MAC_TCL) && !defined(TCL_MAC_USE_MSL_EPOCH)
38 # define START_OF_TIME 1904
39 # define END_OF_TIME 2039
42 # define START_OF_TIME 1902
43 # define END_OF_TIME 2037
47 * The offset of tm_year of struct tm returned by localtime, gmtime, etc.
48 * I don't know how universal this is; K&R II, the NetBSD manpages, and
49 * ../compat/strftime.c all agree that tm_year is the year-1900. However,
50 * some systems may have a different value. This #define should be the
51 * same as in ../compat/strftime.c.
53 #define TM_YEAR_BASE 1900
55 #define HOUR(x) ((int) (60 * x))
56 #define SECSPERDAY (24L * 60L * 60L)
57 #define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
60 * An entry in the lexical lookup table.
62 typedef struct _TABLE {
70 * Daylight-savings mode: on, off, or not yet known.
72 typedef enum _DSTMODE {
73 DSTon, DSToff, DSTmaybe
77 * Meridian: am, pm, or 24-hour style.
79 typedef enum _MERIDIAN {
85 * Global variables. We could get rid of most of these by using a good
86 * union as the yacc stack. (This routine was originally written before
87 * yacc had the %union construct.) Maybe someday; right now we only use
88 * the %union very rarely.
91 static DSTMODE yyDSTmode;
92 static time_t yyDayOrdinal;
93 static time_t yyDayNumber;
94 static time_t yyMonthOrdinal;
95 static int yyHaveDate;
97 static int yyHaveOrdinalMonth;
99 static int yyHaveTime;
100 static int yyHaveZone;
101 static time_t yyTimezone;
103 static time_t yyHour;
104 static time_t yyMinutes;
105 static time_t yyMonth;
106 static time_t yySeconds;
107 static time_t yyYear;
108 static MERIDIAN yyMeridian;
109 static time_t yyRelMonth;
110 static time_t yyRelDay;
111 static time_t yyRelSeconds;
112 static time_t *yyRelPointer;
115 * Prototypes of internal functions.
117 static void yyerror _ANSI_ARGS_((char *s));
118 static time_t ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes,
119 time_t Seconds, MERIDIAN Meridian));
120 static int Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year,
121 time_t Hours, time_t Minutes, time_t Seconds,
122 MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr));
123 static time_t DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future));
124 static time_t NamedDay _ANSI_ARGS_((time_t Start, time_t DayOrdinal,
126 static time_t NamedMonth _ANSI_ARGS_((time_t Start, time_t MonthOrdinal,
127 time_t MonthNumber));
128 static int RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth,
130 static int RelativeDay _ANSI_ARGS_((time_t Start, time_t RelDay,
132 static int LookupWord _ANSI_ARGS_((char *buff));
133 static int yylex _ANSI_ARGS_((void));
136 yyparse _ANSI_ARGS_((void));
141 enum _MERIDIAN Meridian;
144 %token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
145 %token tSTARDATE tSEC_UNIT tSNUMBER tUNUMBER tZONE tEPOCH tDST tISOBASE
146 %token tDAY_UNIT tNEXT
148 %type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT tDST
149 %type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE tISOBASE tDAY_UNIT
150 %type <Number> unit sign tNEXT tSTARDATE
151 %type <Meridian> tMERIDIAN o_merid
169 yyHaveOrdinalMonth++;
189 time : tUNUMBER tMERIDIAN {
195 | tUNUMBER ':' tUNUMBER o_merid {
201 | tUNUMBER ':' tUNUMBER '-' tUNUMBER {
206 yyTimezone = ($5 % 100 + ($5 / 100) * 60);
208 | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
214 | tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER {
220 yyTimezone = ($7 % 100 + ($7 / 100) * 60);
250 | sign tUNUMBER tDAY {
251 yyDayOrdinal = $1 * $2;
260 date : tUNUMBER '/' tUNUMBER {
264 | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
271 yyMonth = ($1 % 10000)/100;
274 | tUNUMBER '-' tMONTH '-' tUNUMBER {
279 | tUNUMBER '-' tUNUMBER '-' tUNUMBER {
288 | tMONTH tUNUMBER ',' tUNUMBER {
302 | tUNUMBER tMONTH tUNUMBER {
309 ordMonth: tNEXT tMONTH {
313 | tNEXT tUNUMBER tMONTH {
319 iso : tISOBASE tZONE tISOBASE {
320 if ($2 != HOUR(- 7)) YYABORT;
322 yyMonth = ($1 % 10000)/100;
325 yyMinutes = ($3 % 10000)/100;
326 yySeconds = $3 % 100;
328 | tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER {
329 if ($2 != HOUR(- 7)) YYABORT;
331 yyMonth = ($1 % 10000)/100;
337 | tISOBASE tISOBASE {
339 yyMonth = ($1 % 10000)/100;
342 yyMinutes = ($2 % 10000)/100;
343 yySeconds = $2 % 100;
347 trek : tSTARDATE tUNUMBER '.' tUNUMBER {
349 * Offset computed year by -377 so that the returned years will
350 * be in a range accessible with a 32 bit clock seconds value
352 yyYear = $2/1000 + 2323 - 377;
355 yyRelDay += (($2%1000)*(365 + IsLeapYear(yyYear)))/1000;
356 yyRelSeconds += $4 * 144 * 60;
360 relspec : relunits tAGO {
367 relunits : sign tUNUMBER unit { *yyRelPointer += $1 * $2 * $3; }
368 | tUNUMBER unit { *yyRelPointer += $1 * $2; }
369 | tNEXT unit { *yyRelPointer += $2; }
370 | tNEXT tUNUMBER unit { *yyRelPointer += $2 * $3; }
371 | unit { *yyRelPointer += $1; }
373 sign : '-' { $$ = -1; }
376 unit : tSEC_UNIT { $$ = $1; yyRelPointer = &yyRelSeconds; }
377 | tDAY_UNIT { $$ = $1; yyRelPointer = &yyRelDay; }
378 | tMONTH_UNIT { $$ = $1; yyRelPointer = &yyRelMonth; }
383 if (yyHaveTime && yyHaveDate && !yyHaveRel) {
392 yyMinutes = $1 % 100;
400 o_merid : /* NULL */ {
411 * Month and day table.
413 static TABLE MonthDayTable[] = {
414 { "january", tMONTH, 1 },
415 { "february", tMONTH, 2 },
416 { "march", tMONTH, 3 },
417 { "april", tMONTH, 4 },
418 { "may", tMONTH, 5 },
419 { "june", tMONTH, 6 },
420 { "july", tMONTH, 7 },
421 { "august", tMONTH, 8 },
422 { "september", tMONTH, 9 },
423 { "sept", tMONTH, 9 },
424 { "october", tMONTH, 10 },
425 { "november", tMONTH, 11 },
426 { "december", tMONTH, 12 },
427 { "sunday", tDAY, 0 },
428 { "monday", tDAY, 1 },
429 { "tuesday", tDAY, 2 },
431 { "wednesday", tDAY, 3 },
432 { "wednes", tDAY, 3 },
433 { "thursday", tDAY, 4 },
435 { "thurs", tDAY, 4 },
436 { "friday", tDAY, 5 },
437 { "saturday", tDAY, 6 },
444 static TABLE UnitsTable[] = {
445 { "year", tMONTH_UNIT, 12 },
446 { "month", tMONTH_UNIT, 1 },
447 { "fortnight", tDAY_UNIT, 14 },
448 { "week", tDAY_UNIT, 7 },
449 { "day", tDAY_UNIT, 1 },
450 { "hour", tSEC_UNIT, 60 * 60 },
451 { "minute", tSEC_UNIT, 60 },
452 { "min", tSEC_UNIT, 60 },
453 { "second", tSEC_UNIT, 1 },
454 { "sec", tSEC_UNIT, 1 },
459 * Assorted relative-time words.
461 static TABLE OtherTable[] = {
462 { "tomorrow", tDAY_UNIT, 1 },
463 { "yesterday", tDAY_UNIT, -1 },
464 { "today", tDAY_UNIT, 0 },
465 { "now", tSEC_UNIT, 0 },
466 { "last", tUNUMBER, -1 },
467 { "this", tSEC_UNIT, 0 },
468 { "next", tNEXT, 1 },
470 { "first", tUNUMBER, 1 },
471 { "second", tUNUMBER, 2 },
472 { "third", tUNUMBER, 3 },
473 { "fourth", tUNUMBER, 4 },
474 { "fifth", tUNUMBER, 5 },
475 { "sixth", tUNUMBER, 6 },
476 { "seventh", tUNUMBER, 7 },
477 { "eighth", tUNUMBER, 8 },
478 { "ninth", tUNUMBER, 9 },
479 { "tenth", tUNUMBER, 10 },
480 { "eleventh", tUNUMBER, 11 },
481 { "twelfth", tUNUMBER, 12 },
484 { "epoch", tEPOCH, 0 },
485 { "stardate", tSTARDATE, 0},
490 * The timezone table. (Note: This table was modified to not use any floating
491 * point constants to work around an SGI compiler bug).
493 static TABLE TimezoneTable[] = {
494 { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
495 { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
496 { "utc", tZONE, HOUR( 0) },
497 { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */
498 { "wet", tZONE, HOUR( 0) }, /* Western European */
499 { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
500 { "wat", tZONE, HOUR( 1) }, /* West Africa */
501 { "at", tZONE, HOUR( 2) }, /* Azores */
503 /* For completeness. BST is also British Summer, and GST is
504 * also Guam Standard. */
505 { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
506 { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
508 { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */
509 { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */
510 { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
511 { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
512 { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
513 { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
514 { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
515 { "cst", tZONE, HOUR( 6) }, /* Central Standard */
516 { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
517 { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
518 { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
519 { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
520 { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
521 { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
522 { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
523 { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
524 { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
525 { "cat", tZONE, HOUR(10) }, /* Central Alaska */
526 { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
527 { "nt", tZONE, HOUR(11) }, /* Nome */
528 { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
529 { "cet", tZONE, -HOUR( 1) }, /* Central European */
530 { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
531 { "met", tZONE, -HOUR( 1) }, /* Middle European */
532 { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */
533 { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */
534 { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */
535 { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */
536 { "fwt", tZONE, -HOUR( 1) }, /* French Winter */
537 { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */
538 { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
539 { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
540 { "it", tZONE, -HOUR( 7/2) }, /* Iran */
541 { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
542 { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
543 { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */
544 { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
546 /* For completeness. NST is also Newfoundland Stanard, nad SST is
547 * also Swedish Summer. */
548 { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */
549 { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */
551 { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */
552 { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
553 { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
554 { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
555 { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
556 { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */
557 { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */
558 { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */
559 { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
560 { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
561 { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
562 { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
563 { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
564 { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
565 { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
566 { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
567 { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
568 /* ADDED BY Marco Nijdam */
569 { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */
575 * Military timezone table.
577 static TABLE MilitaryTable[] = {
578 { "a", tZONE, HOUR( 1) },
579 { "b", tZONE, HOUR( 2) },
580 { "c", tZONE, HOUR( 3) },
581 { "d", tZONE, HOUR( 4) },
582 { "e", tZONE, HOUR( 5) },
583 { "f", tZONE, HOUR( 6) },
584 { "g", tZONE, HOUR( 7) },
585 { "h", tZONE, HOUR( 8) },
586 { "i", tZONE, HOUR( 9) },
587 { "k", tZONE, HOUR( 10) },
588 { "l", tZONE, HOUR( 11) },
589 { "m", tZONE, HOUR( 12) },
590 { "n", tZONE, HOUR(- 1) },
591 { "o", tZONE, HOUR(- 2) },
592 { "p", tZONE, HOUR(- 3) },
593 { "q", tZONE, HOUR(- 4) },
594 { "r", tZONE, HOUR(- 5) },
595 { "s", tZONE, HOUR(- 6) },
596 { "t", tZONE, HOUR(- 7) },
597 { "u", tZONE, HOUR(- 8) },
598 { "v", tZONE, HOUR(- 9) },
599 { "w", tZONE, HOUR(-10) },
600 { "x", tZONE, HOUR(-11) },
601 { "y", tZONE, HOUR(-12) },
602 { "z", tZONE, HOUR( 0) },
608 * Dump error messages in the bit bucket.
618 ToSeconds(Hours, Minutes, Seconds, Meridian)
624 if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
628 if (Hours < 0 || Hours > 23)
630 return (Hours * 60L + Minutes) * 60L + Seconds;
632 if (Hours < 1 || Hours > 12)
634 return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
636 if (Hours < 1 || Hours > 12)
638 return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
640 return -1; /* Should never be reached */
644 *-----------------------------------------------------------------------------
648 * Convert a {month, day, year, hours, minutes, seconds, meridian, dst}
649 * tuple into a clock seconds value.
652 * 0 or -1 indicating success or failure.
655 * Fills TimePtr with the computed value.
657 *-----------------------------------------------------------------------------
660 Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr)
671 static int DaysInMonth[12] = {
672 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
678 /* Figure out how many days are in February for the given year.
679 * Every year divisible by 4 is a leap year.
680 * But, every year divisible by 100 is not a leap year.
681 * But, every year divisible by 400 is a leap year after all.
683 DaysInMonth[1] = IsLeapYear(Year) ? 29 : 28;
685 /* Check the inputs for validity */
686 if (Month < 1 || Month > 12
687 || Year < START_OF_TIME || Year > END_OF_TIME
688 || Day < 1 || Day > DaysInMonth[(int)--Month])
691 /* Start computing the value. First determine the number of days
692 * represented by the date, then multiply by the number of seconds/day.
694 for (Julian = Day - 1, i = 0; i < Month; i++)
695 Julian += DaysInMonth[i];
697 for (i = EPOCH; i < Year; i++)
698 Julian += 365 + IsLeapYear(i);
700 for (i = Year; i < EPOCH; i++)
701 Julian -= 365 + IsLeapYear(i);
703 Julian *= SECSPERDAY;
705 /* Add the timezone offset ?? */
706 Julian += yyTimezone * 60L;
708 /* Add the number of seconds represented by the time component */
709 if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
713 /* Perform a preliminary DST compensation ?? */
715 || (DSTmode == DSTmaybe && TclpGetDate((TclpTime_t)&Julian, 0)->tm_isdst))
723 DSTcorrect(Start, Future)
729 StartDay = (TclpGetDate((TclpTime_t)&Start, 0)->tm_hour + 1) % 24;
730 FutureDay = (TclpGetDate((TclpTime_t)&Future, 0)->tm_hour + 1) % 24;
731 return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
736 NamedDay(Start, DayOrdinal, DayNumber)
745 tm = TclpGetDate((TclpTime_t)&now, 0);
746 now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
747 now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
748 return DSTcorrect(Start, now);
752 NamedMonth(Start, MonthOrdinal, MonthNumber)
762 tm = TclpGetDate((TclpTime_t)&now, 0);
763 /* To compute the next n'th month, we use this alg:
764 * add n to year value
765 * if currentMonth < requestedMonth decrement year value by 1 (so that
766 * doing next february from january gives us february of the current year)
767 * set day to 1, time to 0
769 tm->tm_year += MonthOrdinal;
770 if (tm->tm_mon < MonthNumber - 1) {
773 result = Convert(MonthNumber, (time_t) 1, tm->tm_year + TM_YEAR_BASE,
774 (time_t) 0, (time_t) 0, (time_t) 0, MER24, DSTmaybe, &now);
778 return DSTcorrect(Start, now);
782 RelativeMonth(Start, RelMonth, TimePtr)
797 tm = TclpGetDate((TclpTime_t)&Start, 0);
798 Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth;
800 Month = Month % 12 + 1;
801 result = Convert(Month, (time_t) tm->tm_mday, Year,
802 (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
803 MER24, DSTmaybe, &Julian);
806 * The Julian time returned above is behind by one day, if "month"
807 * or "year" is used to specify relative time and the GMT flag is true.
808 * This problem occurs only when the current time is closer to
809 * midnight, the difference being not more than its time difference
810 * with GMT. For example, in US/Pacific time zone, the problem occurs
811 * whenever the current time is between midnight to 8:00am or 7:00amDST.
812 * See Bug# 413397 for more details and sample script.
813 * To resolve this bug, we simply add the number of seconds corresponding
814 * to timezone difference with GMT to Julian time, if GMT flag is true.
817 if (TclDateTimezone == 0) {
818 Julian += TclpGetTimeZone((unsigned long) Start) * 60L;
822 * The following iteration takes into account the case were we jump
823 * into a "short month". Far example, "one month from Jan 31" will
824 * fail because there is no Feb 31. The code below will reduce the
825 * day and try converting the date until we succed or the date equals
826 * 28 (which always works unless the date is bad in another way).
829 while ((result != 0) && (tm->tm_mday > 28)) {
831 result = Convert(Month, (time_t) tm->tm_mday, Year,
832 (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
833 MER24, DSTmaybe, &Julian);
838 *TimePtr = DSTcorrect(Start, Julian);
844 *-----------------------------------------------------------------------------
848 * Given a starting time and a number of days before or after, compute the
849 * DST corrected difference between those dates.
852 * 1 or -1 indicating success or failure.
855 * Fills TimePtr with the computed value.
857 *-----------------------------------------------------------------------------
861 RelativeDay(Start, RelDay, TimePtr)
868 new = Start + (RelDay * 60 * 60 * 24);
869 *TimePtr = DSTcorrect(Start, new);
887 Tcl_UtfToLower(buff);
889 if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
890 yylval.Meridian = MERam;
893 if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
894 yylval.Meridian = MERpm;
899 * See if we have an abbreviation for a month.
901 if (strlen(buff) == 3) {
903 } else if (strlen(buff) == 4 && buff[3] == '.') {
910 for (tp = MonthDayTable; tp->name; tp++) {
912 if (strncmp(buff, tp->name, 3) == 0) {
913 yylval.Number = tp->value;
916 } else if (strcmp(buff, tp->name) == 0) {
917 yylval.Number = tp->value;
922 for (tp = TimezoneTable; tp->name; tp++) {
923 if (strcmp(buff, tp->name) == 0) {
924 yylval.Number = tp->value;
929 for (tp = UnitsTable; tp->name; tp++) {
930 if (strcmp(buff, tp->name) == 0) {
931 yylval.Number = tp->value;
937 * Strip off any plural and try the units table again.
939 i = strlen(buff) - 1;
940 if (buff[i] == 's') {
942 for (tp = UnitsTable; tp->name; tp++) {
943 if (strcmp(buff, tp->name) == 0) {
944 yylval.Number = tp->value;
950 for (tp = OtherTable; tp->name; tp++) {
951 if (strcmp(buff, tp->name) == 0) {
952 yylval.Number = tp->value;
958 * Military timezones.
960 if (buff[1] == '\0' && !(*buff & 0x80)
961 && isalpha(UCHAR(*buff))) { /* INTL: ISO only */
962 for (tp = MilitaryTable; tp->name; tp++) {
963 if (strcmp(buff, tp->name) == 0) {
964 yylval.Number = tp->value;
971 * Drop out any periods and try the timezone table again.
973 for (i = 0, p = q = buff; *q; q++)
981 for (tp = TimezoneTable; tp->name; tp++) {
982 if (strcmp(buff, tp->name) == 0) {
983 yylval.Number = tp->value;
1002 while (isspace(UCHAR(*yyInput))) {
1006 if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */
1007 /* convert the string into a number; count the number of digits */
1009 for (yylval.Number = 0;
1010 isdigit(UCHAR(c = *yyInput++)); ) { /* INTL: digit */
1011 yylval.Number = 10 * yylval.Number + c - '0';
1015 /* A number with 6 or more digits is considered an ISO 8601 base */
1022 if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
1023 for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
1025 if (p < &buff[sizeof buff - 1]) {
1031 return LookupWord(buff);
1041 } else if (c == '(') {
1043 } else if (c == ')') {
1046 } while (Count > 0);
1051 * Specify zone is of -50000 to force GMT. (This allows BST to work).
1055 TclGetDate(p, now, zone, timePtr)
1059 Tcl_WideInt *timePtr;
1068 /* now has to be cast to a time_t for 64bit compliance */
1069 Start = (time_t) now;
1070 tm = TclpGetDate((TclpTime_t) &Start, (zone == -50000));
1071 thisyear = tm->tm_year + TM_YEAR_BASE;
1073 yyMonth = tm->tm_mon + 1;
1074 yyDay = tm->tm_mday;
1076 if (zone == -50000) {
1077 yyDSTmode = DSToff; /* assume GMT */
1080 yyDSTmode = DSTmaybe;
1089 yyRelPointer = NULL;
1093 yyHaveOrdinalMonth = 0;
1098 if (yyparse() || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 ||
1099 yyHaveDay > 1 || yyHaveOrdinalMonth > 1) {
1103 if (yyHaveDate || yyHaveTime || yyHaveDay) {
1104 if (TclDateYear < 0) {
1105 TclDateYear = -TclDateYear;
1108 * The following line handles years that are specified using
1109 * only two digits. The line of code below implements a policy
1110 * defined by the X/Open workgroup on the millinium rollover.
1111 * Note: some of those dates may not actually be valid on some
1112 * platforms. The POSIX standard startes that the dates 70-99
1113 * shall refer to 1970-1999 and 00-38 shall refer to 2000-2038.
1114 * This later definition should work on all platforms.
1117 if (TclDateYear < 100) {
1118 if (TclDateYear >= 69) {
1119 TclDateYear += 1900;
1121 TclDateYear += 2000;
1124 if (Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
1125 yyMeridian, yyDSTmode, &Start) < 0) {
1129 Start = (time_t) now;
1131 Start -= ((tm->tm_hour * 60L * 60L) +
1132 tm->tm_min * 60L) + tm->tm_sec;
1136 Start += yyRelSeconds;
1137 if (RelativeMonth(Start, yyRelMonth, &Time) < 0) {
1142 if (RelativeDay(Start, yyRelDay, &Time) < 0) {
1147 if (yyHaveDay && !yyHaveDate) {
1148 tod = NamedDay(Start, yyDayOrdinal, yyDayNumber);
1152 if (yyHaveOrdinalMonth) {
1153 tod = NamedMonth(Start, yyMonthOrdinal, yyMonth);