os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclDate.c
Update contrib.
4 * This file is generated from a yacc grammar defined in
5 * the file tclGetDate.y. It should not be edited directly.
7 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
8 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * RCS: @(#) $Id: tclDate.c,v 1.20.4.3 2006/06/14 15:21:14 patthoyts Exp $
19 #if defined(MAC_TCL) && !defined(TCL_MAC_USE_MSL_EPOCH)
21 # define START_OF_TIME 1904
22 # define END_OF_TIME 2039
25 # define START_OF_TIME 1902
26 # define END_OF_TIME 2037
30 * The offset of tm_year of struct tm returned by localtime, gmtime, etc.
31 * I don't know how universal this is; K&R II, the NetBSD manpages, and
32 * ../compat/strftime.c all agree that tm_year is the year-1900. However,
33 * some systems may have a different value. This #define should be the
34 * same as in ../compat/strftime.c.
36 #define TM_YEAR_BASE 1900
38 #define HOUR(x) ((int) (60 * x))
39 #define SECSPERDAY (24L * 60L * 60L)
40 #define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
43 * An entry in the lexical lookup table.
45 typedef struct _TABLE {
53 * Daylight-savings mode: on, off, or not yet known.
55 typedef enum _DSTMODE {
56 DSTon, DSToff, DSTmaybe
60 * Meridian: am, pm, or 24-hour style.
62 typedef enum _MERIDIAN {
68 * Global variables. We could get rid of most of these by using a good
69 * union as the yacc stack. (This routine was originally written before
70 * yacc had the %union construct.) Maybe someday; right now we only use
71 * the %union very rarely.
73 static char *TclDateInput;
74 static DSTMODE TclDateDSTmode;
75 static time_t TclDateDayOrdinal;
76 static time_t TclDateDayNumber;
77 static time_t TclDateMonthOrdinal;
78 static int TclDateHaveDate;
79 static int TclDateHaveDay;
80 static int TclDateHaveOrdinalMonth;
81 static int TclDateHaveRel;
82 static int TclDateHaveTime;
83 static int TclDateHaveZone;
84 static time_t TclDateTimezone;
85 static time_t TclDateDay;
86 static time_t TclDateHour;
87 static time_t TclDateMinutes;
88 static time_t TclDateMonth;
89 static time_t TclDateSeconds;
90 static time_t TclDateYear;
91 static MERIDIAN TclDateMeridian;
92 static time_t TclDateRelMonth;
93 static time_t TclDateRelDay;
94 static time_t TclDateRelSeconds;
95 static time_t *TclDateRelPointer;
98 * Prototypes of internal functions.
100 static void TclDateerror _ANSI_ARGS_((char *s));
101 static time_t ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes,
102 time_t Seconds, MERIDIAN Meridian));
103 static int Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year,
104 time_t Hours, time_t Minutes, time_t Seconds,
105 MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr));
106 static time_t DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future));
107 static time_t NamedDay _ANSI_ARGS_((time_t Start, time_t DayOrdinal,
109 static time_t NamedMonth _ANSI_ARGS_((time_t Start, time_t MonthOrdinal,
110 time_t MonthNumber));
111 static int RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth,
113 static int RelativeDay _ANSI_ARGS_((time_t Start, time_t RelDay,
115 static int LookupWord _ANSI_ARGS_((char *buff));
116 static int TclDatelex _ANSI_ARGS_((void));
119 TclDateparse _ANSI_ARGS_((void));
126 enum _MERIDIAN Meridian;
130 # define tDAYZONE 259
132 # define tMERIDIAN 261
133 # define tMINUTE_UNIT 262
135 # define tMONTH_UNIT 264
136 # define tSTARDATE 265
137 # define tSEC_UNIT 266
138 # define tSNUMBER 267
139 # define tUNUMBER 268
143 # define tISOBASE 272
144 # define tDAY_UNIT 273
150 #if defined(__cplusplus) || defined(__STDC__)
152 #if defined(__cplusplus) && defined(__EXTERN_C__)
156 #if defined(__cplusplus)
157 void TclDateerror(CONST char *);
161 int TclDatelex(void);
163 int TclDateparse(void);
164 #if defined(__cplusplus) && defined(__EXTERN_C__)
170 #define TclDateclearin TclDatechar = -1
171 #define TclDateerrok TclDateerrflag = 0
172 extern int TclDatechar;
173 extern int TclDateerrflag;
176 typedef int TclDatetabelem;
178 #define YYMAXDEPTH 150
181 int TclDate_TclDates[YYMAXDEPTH], *TclDates = TclDate_TclDates;
182 YYSTYPE TclDate_TclDatev[YYMAXDEPTH], *TclDatev = TclDate_TclDatev;
183 #else /* user does initial allocation */
187 static int TclDatemaxdepth = YYMAXDEPTH;
188 # define YYERRCODE 256
192 * Month and day table.
194 static TABLE MonthDayTable[] = {
195 { "january", tMONTH, 1 },
196 { "february", tMONTH, 2 },
197 { "march", tMONTH, 3 },
198 { "april", tMONTH, 4 },
199 { "may", tMONTH, 5 },
200 { "june", tMONTH, 6 },
201 { "july", tMONTH, 7 },
202 { "august", tMONTH, 8 },
203 { "september", tMONTH, 9 },
204 { "sept", tMONTH, 9 },
205 { "october", tMONTH, 10 },
206 { "november", tMONTH, 11 },
207 { "december", tMONTH, 12 },
208 { "sunday", tDAY, 0 },
209 { "monday", tDAY, 1 },
210 { "tuesday", tDAY, 2 },
212 { "wednesday", tDAY, 3 },
213 { "wednes", tDAY, 3 },
214 { "thursday", tDAY, 4 },
216 { "thurs", tDAY, 4 },
217 { "friday", tDAY, 5 },
218 { "saturday", tDAY, 6 },
225 static TABLE UnitsTable[] = {
226 { "year", tMONTH_UNIT, 12 },
227 { "month", tMONTH_UNIT, 1 },
228 { "fortnight", tDAY_UNIT, 14 },
229 { "week", tDAY_UNIT, 7 },
230 { "day", tDAY_UNIT, 1 },
231 { "hour", tSEC_UNIT, 60 * 60 },
232 { "minute", tSEC_UNIT, 60 },
233 { "min", tSEC_UNIT, 60 },
234 { "second", tSEC_UNIT, 1 },
235 { "sec", tSEC_UNIT, 1 },
240 * Assorted relative-time words.
242 static TABLE OtherTable[] = {
243 { "tomorrow", tDAY_UNIT, 1 },
244 { "yesterday", tDAY_UNIT, -1 },
245 { "today", tDAY_UNIT, 0 },
246 { "now", tSEC_UNIT, 0 },
247 { "last", tUNUMBER, -1 },
248 { "this", tSEC_UNIT, 0 },
249 { "next", tNEXT, 1 },
251 { "first", tUNUMBER, 1 },
252 { "second", tUNUMBER, 2 },
253 { "third", tUNUMBER, 3 },
254 { "fourth", tUNUMBER, 4 },
255 { "fifth", tUNUMBER, 5 },
256 { "sixth", tUNUMBER, 6 },
257 { "seventh", tUNUMBER, 7 },
258 { "eighth", tUNUMBER, 8 },
259 { "ninth", tUNUMBER, 9 },
260 { "tenth", tUNUMBER, 10 },
261 { "eleventh", tUNUMBER, 11 },
262 { "twelfth", tUNUMBER, 12 },
265 { "epoch", tEPOCH, 0 },
266 { "stardate", tSTARDATE, 0},
271 * The timezone table. (Note: This table was modified to not use any floating
272 * point constants to work around an SGI compiler bug).
274 static TABLE TimezoneTable[] = {
275 { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
276 { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
277 { "utc", tZONE, HOUR( 0) },
278 { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */
279 { "wet", tZONE, HOUR( 0) }, /* Western European */
280 { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
281 { "wat", tZONE, HOUR( 1) }, /* West Africa */
282 { "at", tZONE, HOUR( 2) }, /* Azores */
284 /* For completeness. BST is also British Summer, and GST is
285 * also Guam Standard. */
286 { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
287 { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
289 { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */
290 { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */
291 { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
292 { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
293 { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
294 { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
295 { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
296 { "cst", tZONE, HOUR( 6) }, /* Central Standard */
297 { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
298 { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
299 { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
300 { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
301 { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
302 { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
303 { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
304 { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
305 { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
306 { "cat", tZONE, HOUR(10) }, /* Central Alaska */
307 { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
308 { "nt", tZONE, HOUR(11) }, /* Nome */
309 { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
310 { "cet", tZONE, -HOUR( 1) }, /* Central European */
311 { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
312 { "met", tZONE, -HOUR( 1) }, /* Middle European */
313 { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */
314 { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */
315 { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */
316 { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */
317 { "fwt", tZONE, -HOUR( 1) }, /* French Winter */
318 { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */
319 { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
320 { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
321 { "it", tZONE, -HOUR( 7/2) }, /* Iran */
322 { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
323 { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
324 { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */
325 { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
327 /* For completeness. NST is also Newfoundland Stanard, nad SST is
328 * also Swedish Summer. */
329 { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */
330 { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */
332 { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */
333 { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
334 { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
335 { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
336 { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
337 { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */
338 { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */
339 { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */
340 { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
341 { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
342 { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
343 { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
344 { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
345 { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
346 { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
347 { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
348 { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
349 /* ADDED BY Marco Nijdam */
350 { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */
356 * Military timezone table.
358 static TABLE MilitaryTable[] = {
359 { "a", tZONE, HOUR( 1) },
360 { "b", tZONE, HOUR( 2) },
361 { "c", tZONE, HOUR( 3) },
362 { "d", tZONE, HOUR( 4) },
363 { "e", tZONE, HOUR( 5) },
364 { "f", tZONE, HOUR( 6) },
365 { "g", tZONE, HOUR( 7) },
366 { "h", tZONE, HOUR( 8) },
367 { "i", tZONE, HOUR( 9) },
368 { "k", tZONE, HOUR( 10) },
369 { "l", tZONE, HOUR( 11) },
370 { "m", tZONE, HOUR( 12) },
371 { "n", tZONE, HOUR(- 1) },
372 { "o", tZONE, HOUR(- 2) },
373 { "p", tZONE, HOUR(- 3) },
374 { "q", tZONE, HOUR(- 4) },
375 { "r", tZONE, HOUR(- 5) },
376 { "s", tZONE, HOUR(- 6) },
377 { "t", tZONE, HOUR(- 7) },
378 { "u", tZONE, HOUR(- 8) },
379 { "v", tZONE, HOUR(- 9) },
380 { "w", tZONE, HOUR(-10) },
381 { "x", tZONE, HOUR(-11) },
382 { "y", tZONE, HOUR(-12) },
383 { "z", tZONE, HOUR( 0) },
389 * Dump error messages in the bit bucket.
399 ToSeconds(Hours, Minutes, Seconds, Meridian)
405 if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
409 if (Hours < 0 || Hours > 23)
411 return (Hours * 60L + Minutes) * 60L + Seconds;
413 if (Hours < 1 || Hours > 12)
415 return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
417 if (Hours < 1 || Hours > 12)
419 return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
421 return -1; /* Should never be reached */
425 *-----------------------------------------------------------------------------
429 * Convert a {month, day, year, hours, minutes, seconds, meridian, dst}
430 * tuple into a clock seconds value.
433 * 0 or -1 indicating success or failure.
436 * Fills TimePtr with the computed value.
438 *-----------------------------------------------------------------------------
441 Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr)
452 static int DaysInMonth[12] = {
453 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
459 /* Figure out how many days are in February for the given year.
460 * Every year divisible by 4 is a leap year.
461 * But, every year divisible by 100 is not a leap year.
462 * But, every year divisible by 400 is a leap year after all.
464 DaysInMonth[1] = IsLeapYear(Year) ? 29 : 28;
466 /* Check the inputs for validity */
467 if (Month < 1 || Month > 12
468 || Year < START_OF_TIME || Year > END_OF_TIME
469 || Day < 1 || Day > DaysInMonth[(int)--Month])
472 /* Start computing the value. First determine the number of days
473 * represented by the date, then multiply by the number of seconds/day.
475 for (Julian = Day - 1, i = 0; i < Month; i++)
476 Julian += DaysInMonth[i];
478 for (i = EPOCH; i < Year; i++)
479 Julian += 365 + IsLeapYear(i);
481 for (i = (int)Year; i < EPOCH; i++)
482 Julian -= 365 + IsLeapYear(i);
484 Julian *= SECSPERDAY;
486 /* Add the timezone offset ?? */
487 Julian += TclDateTimezone * 60L;
489 /* Add the number of seconds represented by the time component */
490 if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
494 /* Perform a preliminary DST compensation ?? */
496 || (DSTmode == DSTmaybe && TclpGetDate((TclpTime_t)&Julian, 0)->tm_isdst))
504 DSTcorrect(Start, Future)
510 StartDay = (TclpGetDate((TclpTime_t)&Start, 0)->tm_hour + 1) % 24;
511 FutureDay = (TclpGetDate((TclpTime_t)&Future, 0)->tm_hour + 1) % 24;
512 return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
517 NamedDay(Start, DayOrdinal, DayNumber)
526 tm = TclpGetDate((TclpTime_t)&now, 0);
527 now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
528 now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
529 return DSTcorrect(Start, now);
533 NamedMonth(Start, MonthOrdinal, MonthNumber)
543 tm = TclpGetDate((TclpTime_t)&now, 0);
544 /* To compute the next n'th month, we use this alg:
545 * add n to year value
546 * if currentMonth < requestedMonth decrement year value by 1 (so that
547 * doing next february from january gives us february of the current year)
548 * set day to 1, time to 0
550 tm->tm_year += (int)MonthOrdinal;
551 if (tm->tm_mon < MonthNumber - 1) {
554 result = Convert(MonthNumber, (time_t) 1, tm->tm_year + TM_YEAR_BASE,
555 (time_t) 0, (time_t) 0, (time_t) 0, MER24, DSTmaybe, &now);
559 return DSTcorrect(Start, now);
563 RelativeMonth(Start, RelMonth, TimePtr)
578 tm = TclpGetDate((TclpTime_t)&Start, 0);
579 Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth;
581 Month = Month % 12 + 1;
582 result = Convert(Month, (time_t) tm->tm_mday, Year,
583 (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
584 MER24, DSTmaybe, &Julian);
587 * The Julian time returned above is behind by one day, if "month"
588 * or "year" is used to specify relative time and the GMT flag is true.
589 * This problem occurs only when the current time is closer to
590 * midnight, the difference being not more than its time difference
591 * with GMT. For example, in US/Pacific time zone, the problem occurs
592 * whenever the current time is between midnight to 8:00am or 7:00amDST.
593 * See Bug# 413397 for more details and sample script.
594 * To resolve this bug, we simply add the number of seconds corresponding
595 * to timezone difference with GMT to Julian time, if GMT flag is true.
598 if (TclDateTimezone == 0) {
599 Julian += TclpGetTimeZone((unsigned long) Start) * 60L;
603 * The following iteration takes into account the case were we jump
604 * into a "short month". Far example, "one month from Jan 31" will
605 * fail because there is no Feb 31. The code below will reduce the
606 * day and try converting the date until we succed or the date equals
607 * 28 (which always works unless the date is bad in another way).
610 while ((result != 0) && (tm->tm_mday > 28)) {
612 result = Convert(Month, (time_t) tm->tm_mday, Year,
613 (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
614 MER24, DSTmaybe, &Julian);
619 *TimePtr = DSTcorrect(Start, Julian);
625 *-----------------------------------------------------------------------------
629 * Given a starting time and a number of days before or after, compute the
630 * DST corrected difference between those dates.
633 * 1 or -1 indicating success or failure.
636 * Fills TimePtr with the computed value.
638 *-----------------------------------------------------------------------------
642 RelativeDay(Start, RelDay, TimePtr)
649 new = Start + (RelDay * 60 * 60 * 24);
650 *TimePtr = DSTcorrect(Start, new);
668 Tcl_UtfToLower(buff);
670 if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
671 TclDatelval.Meridian = MERam;
674 if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
675 TclDatelval.Meridian = MERpm;
680 * See if we have an abbreviation for a month.
682 if (strlen(buff) == 3) {
684 } else if (strlen(buff) == 4 && buff[3] == '.') {
691 for (tp = MonthDayTable; tp->name; tp++) {
693 if (strncmp(buff, tp->name, 3) == 0) {
694 TclDatelval.Number = tp->value;
697 } else if (strcmp(buff, tp->name) == 0) {
698 TclDatelval.Number = tp->value;
703 for (tp = TimezoneTable; tp->name; tp++) {
704 if (strcmp(buff, tp->name) == 0) {
705 TclDatelval.Number = tp->value;
710 for (tp = UnitsTable; tp->name; tp++) {
711 if (strcmp(buff, tp->name) == 0) {
712 TclDatelval.Number = tp->value;
718 * Strip off any plural and try the units table again.
720 i = strlen(buff) - 1;
721 if (buff[i] == 's') {
723 for (tp = UnitsTable; tp->name; tp++) {
724 if (strcmp(buff, tp->name) == 0) {
725 TclDatelval.Number = tp->value;
731 for (tp = OtherTable; tp->name; tp++) {
732 if (strcmp(buff, tp->name) == 0) {
733 TclDatelval.Number = tp->value;
739 * Military timezones.
741 if (buff[1] == '\0' && !(*buff & 0x80)
742 && isalpha(UCHAR(*buff))) { /* INTL: ISO only */
743 for (tp = MilitaryTable; tp->name; tp++) {
744 if (strcmp(buff, tp->name) == 0) {
745 TclDatelval.Number = tp->value;
752 * Drop out any periods and try the timezone table again.
754 for (i = 0, p = q = buff; *q; q++)
762 for (tp = TimezoneTable; tp->name; tp++) {
763 if (strcmp(buff, tp->name) == 0) {
764 TclDatelval.Number = tp->value;
783 while (isspace(UCHAR(*TclDateInput))) {
787 if (isdigit(UCHAR(c = *TclDateInput))) { /* INTL: digit */
788 /* convert the string into a number; count the number of digits */
790 for (TclDatelval.Number = 0;
791 isdigit(UCHAR(c = *TclDateInput++)); ) { /* INTL: digit */
792 TclDatelval.Number = 10 * TclDatelval.Number + c - '0';
796 /* A number with 6 or more digits is considered an ISO 8601 base */
803 if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
804 for (p = buff; isalpha(UCHAR(c = *TclDateInput++)) /* INTL: ISO only. */
806 if (p < &buff[sizeof buff - 1]) {
812 return LookupWord(buff);
815 return *TclDateInput++;
822 } else if (c == '(') {
824 } else if (c == ')') {
832 * Specify zone is of -50000 to force GMT. (This allows BST to work).
836 TclGetDate(p, now, zone, timePtr)
840 Tcl_WideInt *timePtr;
849 /* now has to be cast to a time_t for 64bit compliance */
850 Start = (time_t) now;
851 tm = TclpGetDate((TclpTime_t) &Start, (zone == -50000));
852 thisyear = tm->tm_year + TM_YEAR_BASE;
853 TclDateYear = thisyear;
854 TclDateMonth = tm->tm_mon + 1;
855 TclDateDay = tm->tm_mday;
856 TclDateTimezone = zone;
857 if (zone == -50000) {
858 TclDateDSTmode = DSToff; /* assume GMT */
861 TclDateDSTmode = DSTmaybe;
866 TclDateMeridian = MER24;
867 TclDateRelSeconds = 0;
870 TclDateRelPointer = NULL;
874 TclDateHaveOrdinalMonth = 0;
879 if (TclDateparse() || TclDateHaveTime > 1 || TclDateHaveZone > 1 || TclDateHaveDate > 1 ||
880 TclDateHaveDay > 1 || TclDateHaveOrdinalMonth > 1) {
884 if (TclDateHaveDate || TclDateHaveTime || TclDateHaveDay) {
885 if (TclDateYear < 0) {
886 TclDateYear = -TclDateYear;
889 * The following line handles years that are specified using
890 * only two digits. The line of code below implements a policy
891 * defined by the X/Open workgroup on the millinium rollover.
892 * Note: some of those dates may not actually be valid on some
893 * platforms. The POSIX standard startes that the dates 70-99
894 * shall refer to 1970-1999 and 00-38 shall refer to 2000-2038.
895 * This later definition should work on all platforms.
898 if (TclDateYear < 100) {
899 if (TclDateYear >= 69) {
905 if (Convert(TclDateMonth, TclDateDay, TclDateYear, TclDateHour, TclDateMinutes, TclDateSeconds,
906 TclDateMeridian, TclDateDSTmode, &Start) < 0) {
910 Start = (time_t) now;
911 if (!TclDateHaveRel) {
912 Start -= ((tm->tm_hour * 60L * 60L) +
913 tm->tm_min * 60L) + tm->tm_sec;
917 Start += TclDateRelSeconds;
918 if (RelativeMonth(Start, TclDateRelMonth, &Time) < 0) {
923 if (RelativeDay(Start, TclDateRelDay, &Time) < 0) {
928 if (TclDateHaveDay && !TclDateHaveDate) {
929 tod = NamedDay(Start, TclDateDayOrdinal, TclDateDayNumber);
933 if (TclDateHaveOrdinalMonth) {
934 tod = NamedMonth(Start, TclDateMonthOrdinal, TclDateMonth);
941 static CONST TclDatetabelem TclDateexca[] ={
948 static CONST TclDatetabelem TclDateact[]={
950 24, 40, 23, 36, 54, 81, 41, 28, 53, 26,
951 37, 42, 58, 38, 56, 28, 27, 26, 28, 33,
952 26, 32, 61, 50, 27, 80, 76, 27, 51, 75,
953 74, 73, 30, 72, 71, 70, 69, 52, 49, 48,
954 47, 45, 39, 62, 78, 46, 79, 68, 25, 65,
955 60, 67, 66, 55, 44, 21, 63, 11, 10, 9,
956 8, 35, 7, 6, 5, 4, 3, 43, 2, 1,
957 20, 0, 0, 0, 0, 0, 0, 0, 0, 0,
958 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
959 0, 57, 0, 0, 59, 77, 0, 0, 0, 0,
960 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
961 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
964 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
967 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
968 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
969 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
970 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
971 0, 0, 0, 0, 0, 19, 14, 0, 0, 0,
972 16, 28, 22, 26, 0, 12, 13, 17, 0, 15,
973 27, 18, 31, 0, 0, 29, 0, 34, 28, 0,
974 26, 0, 0, 0, 0, 0, 0, 27, 0, 0,
975 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,
977 static CONST TclDatetabelem TclDatepact[]={
979 -10000000, -43,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,
980 -10000000,-10000000, -26, -268,-10000000, -259, -226,-10000000, -257, 10,
981 -227, -212, -228,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,
982 -229,-10000000, -230, -240, -231,-10000000,-10000000, -264,-10000000, 9,
983 -10000000,-10000000, -249,-10000000,-10000000, -246,-10000000, 4, -2, 2,
984 7, 6,-10000000,-10000000, -11, -232,-10000000,-10000000,-10000000,-10000000,
985 -233,-10000000, -234, -235,-10000000, -237, -238, -239, -242,-10000000,
986 -10000000,-10000000, -1,-10000000,-10000000,-10000000, -12,-10000000, -243, -263,
987 -10000000,-10000000 };
988 static CONST TclDatetabelem TclDatepgo[]={
990 0, 48, 70, 22, 69, 68, 66, 65, 64, 63,
991 62, 60, 59, 58, 57, 55 };
992 static CONST TclDatetabelem TclDater1[]={
994 0, 4, 4, 5, 5, 5, 5, 5, 5, 5,
995 5, 5, 6, 6, 6, 6, 6, 7, 7, 7,
996 10, 10, 10, 10, 10, 8, 8, 8, 8, 8,
997 8, 8, 8, 8, 8, 9, 9, 12, 12, 12,
998 13, 11, 11, 15, 15, 15, 15, 15, 2, 2,
1000 static CONST TclDatetabelem TclDater2[]={
1002 0, 0, 4, 3, 3, 3, 3, 3, 3, 3,
1003 3, 2, 5, 9, 11, 13, 15, 5, 3, 3,
1004 3, 5, 5, 7, 5, 7, 11, 3, 11, 11,
1005 5, 9, 5, 3, 7, 5, 7, 7, 15, 5,
1006 9, 5, 2, 7, 5, 5, 7, 3, 3, 3,
1008 static CONST TclDatetabelem TclDatechk[]={
1010 -10000000, -4, -5, -6, -7, -8, -9, -10, -11, -12,
1011 -13, -14, 268, 269, 259, 272, 263, 270, 274, 258,
1012 -2, -15, 265, 45, 43, -1, 266, 273, 264, 261,
1013 58, 258, 47, 45, 263, -1, 271, 269, 272, 268,
1014 258, 263, 268, -1, 44, 268, 257, 268, 268, 268,
1015 263, 268, 268, 272, 268, 44, 263, -1, 258, -1,
1016 46, -3, 45, 58, 261, 47, 45, 45, 58, 268,
1017 268, 268, 268, 268, 268, 268, 268, -3, 45, 58,
1019 static CONST TclDatetabelem TclDatedef[]={
1021 1, -2, 2, 3, 4, 5, 6, 7, 8, 9,
1022 10, 11, 53, 18, 19, 27, 0, 33, 0, 20,
1023 0, 42, 0, 48, 49, 47, 50, 51, 52, 12,
1024 0, 22, 0, 0, 32, 44, 17, 0, 39, 30,
1025 24, 35, 0, 45, 21, 0, 41, 0, 54, 25,
1026 0, 0, 34, 37, 0, 0, 36, 46, 23, 43,
1027 0, 13, 0, 0, 55, 0, 0, 0, 0, 31,
1028 40, 14, 54, 26, 28, 29, 0, 15, 0, 0,
1034 { char *t_name; int t_val; } TclDatetoktype;
1036 # define YYDEBUG 0 /* don't allow debugging */
1041 TclDatetoktype TclDatetoks[] =
1048 "tMINUTE_UNIT", 262,
1061 "-unknown-", -1 /* ends search */
1064 char * TclDatereds[] =
1066 "-no such reduction-",
1067 "spec : /* empty */",
1078 "time : tUNUMBER tMERIDIAN",
1079 "time : tUNUMBER ':' tUNUMBER o_merid",
1080 "time : tUNUMBER ':' tUNUMBER '-' tUNUMBER",
1081 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
1082 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER",
1083 "zone : tZONE tDST",
1088 "day : tUNUMBER tDAY",
1089 "day : sign tUNUMBER tDAY",
1091 "date : tUNUMBER '/' tUNUMBER",
1092 "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
1094 "date : tUNUMBER '-' tMONTH '-' tUNUMBER",
1095 "date : tUNUMBER '-' tUNUMBER '-' tUNUMBER",
1096 "date : tMONTH tUNUMBER",
1097 "date : tMONTH tUNUMBER ',' tUNUMBER",
1098 "date : tUNUMBER tMONTH",
1100 "date : tUNUMBER tMONTH tUNUMBER",
1101 "ordMonth : tNEXT tMONTH",
1102 "ordMonth : tNEXT tUNUMBER tMONTH",
1103 "iso : tISOBASE tZONE tISOBASE",
1104 "iso : tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER",
1105 "iso : tISOBASE tISOBASE",
1106 "trek : tSTARDATE tUNUMBER '.' tUNUMBER",
1107 "relspec : relunits tAGO",
1108 "relspec : relunits",
1109 "relunits : sign tUNUMBER unit",
1110 "relunits : tUNUMBER unit",
1111 "relunits : tNEXT unit",
1112 "relunits : tNEXT tUNUMBER unit",
1118 "unit : tMONTH_UNIT",
1119 "number : tUNUMBER",
1120 "o_merid : /* empty */",
1121 "o_merid : tMERIDIAN",
1123 #endif /* YYDEBUG */
1125 * Copyright (c) 1993 by Sun Microsystems, Inc.
1130 ** Skeleton parser driver for yacc output
1134 ** yacc user known macros and defines
1136 #define YYERROR goto TclDateerrlab
1137 #define YYACCEPT return(0)
1138 #define YYABORT return(1)
1139 #define YYBACKUP( newtoken, newvalue )\
1141 if ( TclDatechar >= 0 || ( TclDater2[ TclDatetmp ] >> 1 ) != 1 )\
1143 TclDateerror( "syntax error - cannot backup" );\
1144 goto TclDateerrlab;\
1146 TclDatechar = newtoken;\
1147 TclDatestate = *TclDateps;\
1148 TclDatelval = newvalue;\
1149 goto TclDatenewstate;\
1151 #define YYRECOVERING() (!!TclDateerrflag)
1152 #define YYNEW(type) malloc(sizeof(type) * TclDatenewmax)
1153 #define YYCOPY(to, from, type) \
1154 (type *) memcpy(to, (char *) from, TclDatemaxdepth * sizeof (type))
1155 #define YYENLARGE( from, type) \
1156 (type *) realloc((char *) from, TclDatenewmax * sizeof(type))
1158 # define YYDEBUG 1 /* make debugging available */
1162 ** user known globals
1164 int TclDatedebug; /* set to 1 to get debugging */
1167 ** driver internal defines
1169 #define YYFLAG (-10000000)
1172 ** global variables used by the parser
1174 YYSTYPE *TclDatepv; /* top of value stack */
1175 int *TclDateps; /* top of state stack */
1177 int TclDatestate; /* current state */
1178 int TclDatetmp; /* extra var (lasts between blocks) */
1180 int TclDatenerrs; /* number of errors */
1181 int TclDateerrflag; /* error recovery flag */
1182 int TclDatechar; /* current input token number */
1187 #define YYLEX() TclDatecvtok(TclDatelex())
1189 ** TclDatecvtok - return a token if i is a wchar_t value that exceeds 255.
1190 ** If i<255, i itself is the token. If i>255 but the neither
1191 ** of the 30th or 31st bit is on, i is already a token.
1193 #if defined(__STDC__) || defined(__cplusplus)
1194 int TclDatecvtok(int i)
1196 int TclDatecvtok(i) int i;
1200 int last = YYNMBCHARS - 1;
1204 if(i&0x60000000){/*Must convert to a token. */
1205 if( TclDatembchars[last].character < i ){
1206 return i;/*Giving up*/
1208 while ((last>=first)&&(first>=0)) {/*Binary search loop*/
1209 mid = (first+last)/2;
1210 j = TclDatembchars[mid].character;
1211 if( j==i ){/*Found*/
1212 return TclDatembchars[mid].tvalue;
1219 /*No entry in the table.*/
1220 return i;/* Giving up.*/
1221 }else{/* i is already a token. */
1225 #else/*!YYNMBCHARS*/
1226 #define YYLEX() TclDatelex()
1227 #endif/*!YYNMBCHARS*/
1230 ** TclDateparse - return 0 if worked, 1 if syntax error not recovered from
1232 #if defined(__STDC__) || defined(__cplusplus)
1233 int TclDateparse(void)
1238 register YYSTYPE *TclDatepvt = 0; /* top of value stack for $vars */
1240 #if defined(__cplusplus) || defined(lint)
1242 hacks to please C++ and lint - goto's inside
1243 switch should never be executed
1245 static int __yaccpar_lint_hack__ = 0;
1246 switch (__yaccpar_lint_hack__)
1248 case 1: goto TclDateerrlab;
1249 case 2: goto TclDatenewstate;
1254 ** Initialize externals - TclDateparse may be called more than once
1256 TclDatepv = &TclDatev[-1];
1257 TclDateps = &TclDates[-1];
1265 if (TclDatemaxdepth <= 0)
1267 if ((TclDatemaxdepth = YYEXPAND(0)) <= 0)
1269 TclDateerror("yacc initialization error");
1276 register YYSTYPE *TclDate_pv; /* top of value stack */
1277 register int *TclDate_ps; /* top of state stack */
1278 register int TclDate_state; /* current state */
1279 register int TclDate_n; /* internal state number info */
1280 goto TclDatestack; /* moved from 6 lines above to here to please C++ */
1283 ** get globals into registers.
1284 ** branch to here only if YYBACKUP was called.
1286 TclDate_pv = TclDatepv;
1287 TclDate_ps = TclDateps;
1288 TclDate_state = TclDatestate;
1289 goto TclDate_newstate;
1292 ** get globals into registers.
1293 ** either we just started, or we just finished a reduction
1296 TclDate_pv = TclDatepv;
1297 TclDate_ps = TclDateps;
1298 TclDate_state = TclDatestate;
1301 ** top of for (;;) loop while no reductions done
1305 ** put a state and value onto the stacks
1309 ** if debugging, look up token value in list of value vs.
1310 ** name pairs. 0 and negative (-1) are special values.
1311 ** Note: linear search is used since time is not a real
1312 ** consideration while debugging.
1316 register int TclDate_i;
1318 printf( "State %d, token ", TclDate_state );
1319 if ( TclDatechar == 0 )
1320 printf( "end-of-file\n" );
1321 else if ( TclDatechar < 0 )
1322 printf( "-none-\n" );
1325 for ( TclDate_i = 0; TclDatetoks[TclDate_i].t_val >= 0;
1328 if ( TclDatetoks[TclDate_i].t_val == TclDatechar )
1331 printf( "%s\n", TclDatetoks[TclDate_i].t_name );
1334 #endif /* YYDEBUG */
1335 if ( ++TclDate_ps >= &TclDates[ TclDatemaxdepth ] ) /* room on stack? */
1338 ** reallocate and recover. Note that pointers
1339 ** have to be reset, or bad things will happen
1341 long TclDateps_index = (TclDate_ps - TclDates);
1342 long TclDatepv_index = (TclDate_pv - TclDatev);
1343 long TclDatepvt_index = (TclDatepvt - TclDatev);
1346 TclDatenewmax = YYEXPAND(TclDatemaxdepth);
1348 TclDatenewmax = 2 * TclDatemaxdepth; /* double table size */
1349 if (TclDatemaxdepth == YYMAXDEPTH) /* first time growth */
1351 char *newTclDates = (char *)YYNEW(int);
1352 char *newTclDatev = (char *)YYNEW(YYSTYPE);
1353 if (newTclDates != 0 && newTclDatev != 0)
1355 TclDates = YYCOPY(newTclDates, TclDates, int);
1356 TclDatev = YYCOPY(newTclDatev, TclDatev, YYSTYPE);
1359 TclDatenewmax = 0; /* failed */
1361 else /* not first time */
1363 TclDates = YYENLARGE(TclDates, int);
1364 TclDatev = YYENLARGE(TclDatev, YYSTYPE);
1365 if (TclDates == 0 || TclDatev == 0)
1366 TclDatenewmax = 0; /* failed */
1369 if (TclDatenewmax <= TclDatemaxdepth) /* tables not expanded */
1371 TclDateerror( "yacc stack overflow" );
1374 TclDatemaxdepth = TclDatenewmax;
1376 TclDate_ps = TclDates + TclDateps_index;
1377 TclDate_pv = TclDatev + TclDatepv_index;
1378 TclDatepvt = TclDatev + TclDatepvt_index;
1380 *TclDate_ps = TclDate_state;
1381 *++TclDate_pv = TclDateval;
1384 ** we have a new state - find out what to do
1387 if ( ( TclDate_n = TclDatepact[ TclDate_state ] ) <= YYFLAG )
1388 goto TclDatedefault; /* simple state */
1391 ** if debugging, need to mark whether new token grabbed
1393 TclDatetmp = TclDatechar < 0;
1395 if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) )
1396 TclDatechar = 0; /* reached EOF */
1398 if ( TclDatedebug && TclDatetmp )
1400 register int TclDate_i;
1402 printf( "Received token " );
1403 if ( TclDatechar == 0 )
1404 printf( "end-of-file\n" );
1405 else if ( TclDatechar < 0 )
1406 printf( "-none-\n" );
1409 for ( TclDate_i = 0; TclDatetoks[TclDate_i].t_val >= 0;
1412 if ( TclDatetoks[TclDate_i].t_val == TclDatechar )
1415 printf( "%s\n", TclDatetoks[TclDate_i].t_name );
1418 #endif /* YYDEBUG */
1419 if ( ( ( TclDate_n += TclDatechar ) < 0 ) || ( TclDate_n >= YYLAST ) )
1420 goto TclDatedefault;
1421 if ( TclDatechk[ TclDate_n = TclDateact[ TclDate_n ] ] == TclDatechar ) /*valid shift*/
1424 TclDateval = TclDatelval;
1425 TclDate_state = TclDate_n;
1426 if ( TclDateerrflag > 0 )
1432 if ( ( TclDate_n = TclDatedef[ TclDate_state ] ) == -2 )
1435 TclDatetmp = TclDatechar < 0;
1437 if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) )
1438 TclDatechar = 0; /* reached EOF */
1440 if ( TclDatedebug && TclDatetmp )
1442 register int TclDate_i;
1444 printf( "Received token " );
1445 if ( TclDatechar == 0 )
1446 printf( "end-of-file\n" );
1447 else if ( TclDatechar < 0 )
1448 printf( "-none-\n" );
1451 for ( TclDate_i = 0;
1452 TclDatetoks[TclDate_i].t_val >= 0;
1455 if ( TclDatetoks[TclDate_i].t_val
1461 printf( "%s\n", TclDatetoks[TclDate_i].t_name );
1464 #endif /* YYDEBUG */
1466 ** look through exception table
1469 register CONST int *TclDatexi = TclDateexca;
1471 while ( ( *TclDatexi != -1 ) ||
1472 ( TclDatexi[1] != TclDate_state ) )
1476 while ( ( *(TclDatexi += 2) >= 0 ) &&
1477 ( *TclDatexi != TclDatechar ) )
1479 if ( ( TclDate_n = TclDatexi[1] ) < 0 )
1485 ** check for syntax error
1487 if ( TclDate_n == 0 ) /* have an error */
1489 /* no worry about speed here! */
1490 switch ( TclDateerrflag )
1492 case 0: /* new error */
1493 TclDateerror( "syntax error" );
1496 ** get globals into registers.
1497 ** we have a user generated syntax type error
1499 TclDate_pv = TclDatepv;
1500 TclDate_ps = TclDateps;
1501 TclDate_state = TclDatestate;
1506 case 2: /* incompletely recovered error */
1510 ** find state where "error" is a legal
1513 while ( TclDate_ps >= TclDates )
1515 TclDate_n = TclDatepact[ *TclDate_ps ] + YYERRCODE;
1516 if ( TclDate_n >= 0 && TclDate_n < YYLAST &&
1517 TclDatechk[TclDateact[TclDate_n]] == YYERRCODE) {
1519 ** simulate shift of "error"
1521 TclDate_state = TclDateact[ TclDate_n ];
1525 ** current state has no shift on
1526 ** "error", pop stack
1529 # define _POP_ "Error recovery pops state %d, uncovers state %d\n"
1531 printf( _POP_, *TclDate_ps,
1539 ** there is no state on stack with "error" as
1540 ** a valid shift. give up.
1543 case 3: /* no shift yet; eat a token */
1546 ** if debugging, look up token in list of
1547 ** pairs. 0 and negative shouldn't occur,
1548 ** but since timing doesn't matter when
1549 ** debugging, it doesn't hurt to leave the
1554 register int TclDate_i;
1556 printf( "Error recovery discards " );
1557 if ( TclDatechar == 0 )
1558 printf( "token end-of-file\n" );
1559 else if ( TclDatechar < 0 )
1560 printf( "token -none-\n" );
1563 for ( TclDate_i = 0;
1564 TclDatetoks[TclDate_i].t_val >= 0;
1567 if ( TclDatetoks[TclDate_i].t_val
1573 printf( "token %s\n",
1574 TclDatetoks[TclDate_i].t_name );
1577 #endif /* YYDEBUG */
1578 if ( TclDatechar == 0 ) /* reached EOF. quit */
1581 goto TclDate_newstate;
1583 }/* end if ( TclDate_n == 0 ) */
1585 ** reduction by production TclDate_n
1586 ** put stack tops, etc. so things right after switch
1590 ** if debugging, print the string that is the user's
1591 ** specification of the reduction which is just about
1595 printf( "Reduce by (%d) \"%s\"\n",
1596 TclDate_n, TclDatereds[ TclDate_n ] );
1598 TclDatetmp = TclDate_n; /* value to switch over */
1599 TclDatepvt = TclDate_pv; /* $vars top of value stack */
1601 ** Look in goto table for next state
1602 ** Sorry about using TclDate_state here as temporary
1603 ** register variable, but why not, if it works...
1604 ** If TclDater2[ TclDate_n ] doesn't have the low order bit
1605 ** set, then there is no action to be done for
1606 ** this reduction. So, no saving & unsaving of
1607 ** registers done. The only difference between the
1608 ** code just after the if and the body of the if is
1609 ** the goto TclDate_stack in the body. This way the test
1610 ** can be made before the choice of what to do is needed.
1613 /* length of production doubled with extra bit */
1614 register int TclDate_len = TclDater2[ TclDate_n ];
1616 if ( !( TclDate_len & 01 ) )
1619 TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */
1620 TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] +
1621 *( TclDate_ps -= TclDate_len ) + 1;
1622 if ( TclDate_state >= YYLAST ||
1623 TclDatechk[ TclDate_state =
1624 TclDateact[ TclDate_state ] ] != -TclDate_n )
1626 TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ];
1631 TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */
1632 TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] +
1633 *( TclDate_ps -= TclDate_len ) + 1;
1634 if ( TclDate_state >= YYLAST ||
1635 TclDatechk[ TclDate_state = TclDateact[ TclDate_state ] ] != -TclDate_n )
1637 TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ];
1640 /* save until reenter driver code */
1641 TclDatestate = TclDate_state;
1642 TclDateps = TclDate_ps;
1643 TclDatepv = TclDate_pv;
1646 ** code supplied by user is placed in this switch
1648 switch( TclDatetmp )
1661 TclDateHaveOrdinalMonth++;
1679 TclDateHour = TclDatepvt[-1].Number;
1682 TclDateMeridian = TclDatepvt[-0].Meridian;
1685 TclDateHour = TclDatepvt[-3].Number;
1686 TclDateMinutes = TclDatepvt[-1].Number;
1688 TclDateMeridian = TclDatepvt[-0].Meridian;
1691 TclDateHour = TclDatepvt[-4].Number;
1692 TclDateMinutes = TclDatepvt[-2].Number;
1693 TclDateMeridian = MER24;
1694 TclDateDSTmode = DSToff;
1695 TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60);
1698 TclDateHour = TclDatepvt[-5].Number;
1699 TclDateMinutes = TclDatepvt[-3].Number;
1700 TclDateSeconds = TclDatepvt[-1].Number;
1701 TclDateMeridian = TclDatepvt[-0].Meridian;
1704 TclDateHour = TclDatepvt[-6].Number;
1705 TclDateMinutes = TclDatepvt[-4].Number;
1706 TclDateSeconds = TclDatepvt[-2].Number;
1707 TclDateMeridian = MER24;
1708 TclDateDSTmode = DSToff;
1709 TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60);
1712 TclDateTimezone = TclDatepvt[-1].Number;
1713 TclDateDSTmode = DSTon;
1716 TclDateTimezone = TclDatepvt[-0].Number;
1717 TclDateDSTmode = DSToff;
1720 TclDateTimezone = TclDatepvt[-0].Number;
1721 TclDateDSTmode = DSTon;
1724 TclDateDayOrdinal = 1;
1725 TclDateDayNumber = TclDatepvt[-0].Number;
1728 TclDateDayOrdinal = 1;
1729 TclDateDayNumber = TclDatepvt[-1].Number;
1732 TclDateDayOrdinal = TclDatepvt[-1].Number;
1733 TclDateDayNumber = TclDatepvt[-0].Number;
1736 TclDateDayOrdinal = TclDatepvt[-2].Number * TclDatepvt[-1].Number;
1737 TclDateDayNumber = TclDatepvt[-0].Number;
1740 TclDateDayOrdinal = 2;
1741 TclDateDayNumber = TclDatepvt[-0].Number;
1744 TclDateMonth = TclDatepvt[-2].Number;
1745 TclDateDay = TclDatepvt[-0].Number;
1748 TclDateMonth = TclDatepvt[-4].Number;
1749 TclDateDay = TclDatepvt[-2].Number;
1750 TclDateYear = TclDatepvt[-0].Number;
1753 TclDateYear = TclDatepvt[-0].Number / 10000;
1754 TclDateMonth = (TclDatepvt[-0].Number % 10000)/100;
1755 TclDateDay = TclDatepvt[-0].Number % 100;
1758 TclDateDay = TclDatepvt[-4].Number;
1759 TclDateMonth = TclDatepvt[-2].Number;
1760 TclDateYear = TclDatepvt[-0].Number;
1763 TclDateMonth = TclDatepvt[-2].Number;
1764 TclDateDay = TclDatepvt[-0].Number;
1765 TclDateYear = TclDatepvt[-4].Number;
1768 TclDateMonth = TclDatepvt[-1].Number;
1769 TclDateDay = TclDatepvt[-0].Number;
1772 TclDateMonth = TclDatepvt[-3].Number;
1773 TclDateDay = TclDatepvt[-2].Number;
1774 TclDateYear = TclDatepvt[-0].Number;
1777 TclDateMonth = TclDatepvt[-0].Number;
1778 TclDateDay = TclDatepvt[-1].Number;
1783 TclDateYear = EPOCH;
1786 TclDateMonth = TclDatepvt[-1].Number;
1787 TclDateDay = TclDatepvt[-2].Number;
1788 TclDateYear = TclDatepvt[-0].Number;
1791 TclDateMonthOrdinal = 1;
1792 TclDateMonth = TclDatepvt[-0].Number;
1795 TclDateMonthOrdinal = TclDatepvt[-1].Number;
1796 TclDateMonth = TclDatepvt[-0].Number;
1799 if (TclDatepvt[-1].Number != HOUR(- 7)) YYABORT;
1800 TclDateYear = TclDatepvt[-2].Number / 10000;
1801 TclDateMonth = (TclDatepvt[-2].Number % 10000)/100;
1802 TclDateDay = TclDatepvt[-2].Number % 100;
1803 TclDateHour = TclDatepvt[-0].Number / 10000;
1804 TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100;
1805 TclDateSeconds = TclDatepvt[-0].Number % 100;
1808 if (TclDatepvt[-5].Number != HOUR(- 7)) YYABORT;
1809 TclDateYear = TclDatepvt[-6].Number / 10000;
1810 TclDateMonth = (TclDatepvt[-6].Number % 10000)/100;
1811 TclDateDay = TclDatepvt[-6].Number % 100;
1812 TclDateHour = TclDatepvt[-4].Number;
1813 TclDateMinutes = TclDatepvt[-2].Number;
1814 TclDateSeconds = TclDatepvt[-0].Number;
1817 TclDateYear = TclDatepvt[-1].Number / 10000;
1818 TclDateMonth = (TclDatepvt[-1].Number % 10000)/100;
1819 TclDateDay = TclDatepvt[-1].Number % 100;
1820 TclDateHour = TclDatepvt[-0].Number / 10000;
1821 TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100;
1822 TclDateSeconds = TclDatepvt[-0].Number % 100;
1826 * Offset computed year by -377 so that the returned years will
1827 * be in a range accessible with a 32 bit clock seconds value
1829 TclDateYear = TclDatepvt[-2].Number/1000 + 2323 - 377;
1832 TclDateRelDay += ((TclDatepvt[-2].Number%1000)*(365 + IsLeapYear(TclDateYear)))/1000;
1833 TclDateRelSeconds += TclDatepvt[-0].Number * 144 * 60;
1836 TclDateRelSeconds *= -1;
1837 TclDateRelMonth *= -1;
1838 TclDateRelDay *= -1;
1840 case 43:{ *TclDateRelPointer += TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
1841 case 44:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
1842 case 45:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break;
1843 case 46:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
1844 case 47:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break;
1845 case 48:{ TclDateval.Number = -1; } break;
1846 case 49:{ TclDateval.Number = 1; } break;
1847 case 50:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelSeconds; } break;
1848 case 51:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelDay; } break;
1849 case 52:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelMonth; } break;
1851 if (TclDateHaveTime && TclDateHaveDate && !TclDateHaveRel) {
1852 TclDateYear = TclDatepvt[-0].Number;
1855 if (TclDatepvt[-0].Number < 100) {
1856 TclDateHour = TclDatepvt[-0].Number;
1859 TclDateHour = TclDatepvt[-0].Number / 100;
1860 TclDateMinutes = TclDatepvt[-0].Number % 100;
1863 TclDateMeridian = MER24;
1867 TclDateval.Meridian = MER24;
1870 TclDateval.Meridian = TclDatepvt[-0].Meridian;
1873 goto TclDatestack; /* reset registers in driver code */