/[dtapublic]/projs/trunk/shared_source/tcl_base/tcldate.c
ViewVC logotype

Contents of /projs/trunk/shared_source/tcl_base/tcldate.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (show annotations) (download)
Fri Oct 14 01:50:00 2016 UTC (8 years, 2 months ago) by dashley
File MIME type: text/plain
File size: 57952 byte(s)
Move shared source code to commonize.
1 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tcl_base/tcldate.c,v 1.1.1.1 2001/06/13 04:36:47 dtashley Exp $ */
2
3 /*
4 * tclDate.c --
5 *
6 * This file is generated from a yacc grammar defined in
7 * the file tclGetDate.y. It should not be edited directly.
8 *
9 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
10 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
11 *
12 * See the file "license.terms" for information on usage and redistribution
13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 *
15 * RCS: @(#) $Id: tcldate.c,v 1.1.1.1 2001/06/13 04:36:47 dtashley Exp $
16 */
17
18 #include "tclInt.h"
19 #include "tclPort.h"
20
21 #ifdef MAC_TCL
22 # define EPOCH 1904
23 # define START_OF_TIME 1904
24 # define END_OF_TIME 2039
25 #else
26 # define EPOCH 1970
27 # define START_OF_TIME 1902
28 # define END_OF_TIME 2037
29 #endif
30
31 /*
32 * The offset of tm_year of struct tm returned by localtime, gmtime, etc.
33 * I don't know how universal this is; K&R II, the NetBSD manpages, and
34 * ../compat/strftime.c all agree that tm_year is the year-1900. However,
35 * some systems may have a different value. This #define should be the
36 * same as in ../compat/strftime.c.
37 */
38 #define TM_YEAR_BASE 1900
39
40 #define HOUR(x) ((int) (60 * x))
41 #define SECSPERDAY (24L * 60L * 60L)
42 #define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
43
44 /*
45 * An entry in the lexical lookup table.
46 */
47 typedef struct _TABLE {
48 char *name;
49 int type;
50 time_t value;
51 } TABLE;
52
53
54 /*
55 * Daylight-savings mode: on, off, or not yet known.
56 */
57 typedef enum _DSTMODE {
58 DSTon, DSToff, DSTmaybe
59 } DSTMODE;
60
61 /*
62 * Meridian: am, pm, or 24-hour style.
63 */
64 typedef enum _MERIDIAN {
65 MERam, MERpm, MER24
66 } MERIDIAN;
67
68
69 /*
70 * Global variables. We could get rid of most of these by using a good
71 * union as the yacc stack. (This routine was originally written before
72 * yacc had the %union construct.) Maybe someday; right now we only use
73 * the %union very rarely.
74 */
75 static char *TclDateInput;
76 static DSTMODE TclDateDSTmode;
77 static time_t TclDateDayOrdinal;
78 static time_t TclDateDayNumber;
79 static time_t TclDateMonthOrdinal;
80 static int TclDateHaveDate;
81 static int TclDateHaveDay;
82 static int TclDateHaveOrdinalMonth;
83 static int TclDateHaveRel;
84 static int TclDateHaveTime;
85 static int TclDateHaveZone;
86 static time_t TclDateTimezone;
87 static time_t TclDateDay;
88 static time_t TclDateHour;
89 static time_t TclDateMinutes;
90 static time_t TclDateMonth;
91 static time_t TclDateSeconds;
92 static time_t TclDateYear;
93 static MERIDIAN TclDateMeridian;
94 static time_t TclDateRelMonth;
95 static time_t TclDateRelDay;
96 static time_t TclDateRelSeconds;
97 static time_t *TclDateRelPointer;
98
99 /*
100 * Prototypes of internal functions.
101 */
102 static void TclDateerror _ANSI_ARGS_((char *s));
103 static time_t ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes,
104 time_t Seconds, MERIDIAN Meridian));
105 static int Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year,
106 time_t Hours, time_t Minutes, time_t Seconds,
107 MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr));
108 static time_t DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future));
109 static time_t NamedDay _ANSI_ARGS_((time_t Start, time_t DayOrdinal,
110 time_t DayNumber));
111 static time_t NamedMonth _ANSI_ARGS_((time_t Start, time_t MonthOrdinal,
112 time_t MonthNumber));
113 static int RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth,
114 time_t *TimePtr));
115 static int RelativeDay _ANSI_ARGS_((time_t Start, time_t RelDay,
116 time_t *TimePtr));
117 static int LookupWord _ANSI_ARGS_((char *buff));
118 static int TclDatelex _ANSI_ARGS_((void));
119
120 int
121 TclDateparse _ANSI_ARGS_((void));
122 typedef union
123 #ifdef __cplusplus
124 YYSTYPE
125 #endif
126 {
127 time_t Number;
128 enum _MERIDIAN Meridian;
129 } YYSTYPE;
130 # define tAGO 257
131 # define tDAY 258
132 # define tDAYZONE 259
133 # define tID 260
134 # define tMERIDIAN 261
135 # define tMINUTE_UNIT 262
136 # define tMONTH 263
137 # define tMONTH_UNIT 264
138 # define tSTARDATE 265
139 # define tSEC_UNIT 266
140 # define tSNUMBER 267
141 # define tUNUMBER 268
142 # define tZONE 269
143 # define tEPOCH 270
144 # define tDST 271
145 # define tISOBASE 272
146 # define tDAY_UNIT 273
147 # define tNEXT 274
148
149
150
151
152 #if defined(__cplusplus) || defined(__STDC__)
153
154 #if defined(__cplusplus) && defined(__EXTERN_C__)
155 extern "C" {
156 #endif
157 #ifndef TclDateerror
158 #if defined(__cplusplus)
159 void TclDateerror(CONST char *);
160 #endif
161 #endif
162 #ifndef TclDatelex
163 int TclDatelex(void);
164 #endif
165 int TclDateparse(void);
166 #if defined(__cplusplus) && defined(__EXTERN_C__)
167 }
168 #endif
169
170 #endif
171
172 #define TclDateclearin TclDatechar = -1
173 #define TclDateerrok TclDateerrflag = 0
174 extern int TclDatechar;
175 extern int TclDateerrflag;
176 YYSTYPE TclDatelval;
177 YYSTYPE TclDateval;
178 typedef int TclDatetabelem;
179 #ifndef YYMAXDEPTH
180 #define YYMAXDEPTH 150
181 #endif
182 #if YYMAXDEPTH > 0
183 int TclDate_TclDates[YYMAXDEPTH], *TclDates = TclDate_TclDates;
184 YYSTYPE TclDate_TclDatev[YYMAXDEPTH], *TclDatev = TclDate_TclDatev;
185 #else /* user does initial allocation */
186 int *TclDates;
187 YYSTYPE *TclDatev;
188 #endif
189 static int TclDatemaxdepth = YYMAXDEPTH;
190 # define YYERRCODE 256
191
192
193 /*
194 * Month and day table.
195 */
196 static TABLE MonthDayTable[] = {
197 { "january", tMONTH, 1 },
198 { "february", tMONTH, 2 },
199 { "march", tMONTH, 3 },
200 { "april", tMONTH, 4 },
201 { "may", tMONTH, 5 },
202 { "june", tMONTH, 6 },
203 { "july", tMONTH, 7 },
204 { "august", tMONTH, 8 },
205 { "september", tMONTH, 9 },
206 { "sept", tMONTH, 9 },
207 { "october", tMONTH, 10 },
208 { "november", tMONTH, 11 },
209 { "december", tMONTH, 12 },
210 { "sunday", tDAY, 0 },
211 { "monday", tDAY, 1 },
212 { "tuesday", tDAY, 2 },
213 { "tues", tDAY, 2 },
214 { "wednesday", tDAY, 3 },
215 { "wednes", tDAY, 3 },
216 { "thursday", tDAY, 4 },
217 { "thur", tDAY, 4 },
218 { "thurs", tDAY, 4 },
219 { "friday", tDAY, 5 },
220 { "saturday", tDAY, 6 },
221 { NULL }
222 };
223
224 /*
225 * Time units table.
226 */
227 static TABLE UnitsTable[] = {
228 { "year", tMONTH_UNIT, 12 },
229 { "month", tMONTH_UNIT, 1 },
230 { "fortnight", tDAY_UNIT, 14 },
231 { "week", tDAY_UNIT, 7 },
232 { "day", tDAY_UNIT, 1 },
233 { "hour", tSEC_UNIT, 60 * 60 },
234 { "minute", tSEC_UNIT, 60 },
235 { "min", tSEC_UNIT, 60 },
236 { "second", tSEC_UNIT, 1 },
237 { "sec", tSEC_UNIT, 1 },
238 { NULL }
239 };
240
241 /*
242 * Assorted relative-time words.
243 */
244 static TABLE OtherTable[] = {
245 { "tomorrow", tDAY_UNIT, 1 },
246 { "yesterday", tDAY_UNIT, -1 },
247 { "today", tDAY_UNIT, 0 },
248 { "now", tSEC_UNIT, 0 },
249 { "last", tUNUMBER, -1 },
250 { "this", tSEC_UNIT, 0 },
251 { "next", tNEXT, 1 },
252 #if 0
253 { "first", tUNUMBER, 1 },
254 { "second", tUNUMBER, 2 },
255 { "third", tUNUMBER, 3 },
256 { "fourth", tUNUMBER, 4 },
257 { "fifth", tUNUMBER, 5 },
258 { "sixth", tUNUMBER, 6 },
259 { "seventh", tUNUMBER, 7 },
260 { "eighth", tUNUMBER, 8 },
261 { "ninth", tUNUMBER, 9 },
262 { "tenth", tUNUMBER, 10 },
263 { "eleventh", tUNUMBER, 11 },
264 { "twelfth", tUNUMBER, 12 },
265 #endif
266 { "ago", tAGO, 1 },
267 { "epoch", tEPOCH, 0 },
268 { "stardate", tSTARDATE, 0},
269 { NULL }
270 };
271
272 /*
273 * The timezone table. (Note: This table was modified to not use any floating
274 * point constants to work around an SGI compiler bug).
275 */
276 static TABLE TimezoneTable[] = {
277 { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
278 { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
279 { "utc", tZONE, HOUR( 0) },
280 { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */
281 { "wet", tZONE, HOUR( 0) }, /* Western European */
282 { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
283 { "wat", tZONE, HOUR( 1) }, /* West Africa */
284 { "at", tZONE, HOUR( 2) }, /* Azores */
285 #if 0
286 /* For completeness. BST is also British Summer, and GST is
287 * also Guam Standard. */
288 { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
289 { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
290 #endif
291 { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */
292 { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */
293 { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
294 { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
295 { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
296 { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
297 { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
298 { "cst", tZONE, HOUR( 6) }, /* Central Standard */
299 { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
300 { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
301 { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
302 { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
303 { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
304 { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
305 { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
306 { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
307 { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
308 { "cat", tZONE, HOUR(10) }, /* Central Alaska */
309 { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
310 { "nt", tZONE, HOUR(11) }, /* Nome */
311 { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
312 { "cet", tZONE, -HOUR( 1) }, /* Central European */
313 { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
314 { "met", tZONE, -HOUR( 1) }, /* Middle European */
315 { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */
316 { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */
317 { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */
318 { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */
319 { "fwt", tZONE, -HOUR( 1) }, /* French Winter */
320 { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */
321 { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
322 { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
323 { "it", tZONE, -HOUR( 7/2) }, /* Iran */
324 { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
325 { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
326 { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */
327 { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
328 #if 0
329 /* For completeness. NST is also Newfoundland Stanard, nad SST is
330 * also Swedish Summer. */
331 { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */
332 { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */
333 #endif /* 0 */
334 { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */
335 { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
336 { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
337 { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
338 { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
339 { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
340 { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
341 { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
342 { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
343 { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
344 { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
345 { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
346 { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
347 { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
348 /* ADDED BY Marco Nijdam */
349 { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */
350 /* End ADDED */
351 { NULL }
352 };
353
354 /*
355 * Military timezone table.
356 */
357 static TABLE MilitaryTable[] = {
358 { "a", tZONE, HOUR( 1) },
359 { "b", tZONE, HOUR( 2) },
360 { "c", tZONE, HOUR( 3) },
361 { "d", tZONE, HOUR( 4) },
362 { "e", tZONE, HOUR( 5) },
363 { "f", tZONE, HOUR( 6) },
364 { "g", tZONE, HOUR( 7) },
365 { "h", tZONE, HOUR( 8) },
366 { "i", tZONE, HOUR( 9) },
367 { "k", tZONE, HOUR( 10) },
368 { "l", tZONE, HOUR( 11) },
369 { "m", tZONE, HOUR( 12) },
370 { "n", tZONE, HOUR(- 1) },
371 { "o", tZONE, HOUR(- 2) },
372 { "p", tZONE, HOUR(- 3) },
373 { "q", tZONE, HOUR(- 4) },
374 { "r", tZONE, HOUR(- 5) },
375 { "s", tZONE, HOUR(- 6) },
376 { "t", tZONE, HOUR(- 7) },
377 { "u", tZONE, HOUR(- 8) },
378 { "v", tZONE, HOUR(- 9) },
379 { "w", tZONE, HOUR(-10) },
380 { "x", tZONE, HOUR(-11) },
381 { "y", tZONE, HOUR(-12) },
382 { "z", tZONE, HOUR( 0) },
383 { NULL }
384 };
385
386
387 /*
388 * Dump error messages in the bit bucket.
389 */
390 static void
391 TclDateerror(s)
392 char *s;
393 {
394 }
395
396
397 static time_t
398 ToSeconds(Hours, Minutes, Seconds, Meridian)
399 time_t Hours;
400 time_t Minutes;
401 time_t Seconds;
402 MERIDIAN Meridian;
403 {
404 if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
405 return -1;
406 switch (Meridian) {
407 case MER24:
408 if (Hours < 0 || Hours > 23)
409 return -1;
410 return (Hours * 60L + Minutes) * 60L + Seconds;
411 case MERam:
412 if (Hours < 1 || Hours > 12)
413 return -1;
414 return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
415 case MERpm:
416 if (Hours < 1 || Hours > 12)
417 return -1;
418 return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
419 }
420 return -1; /* Should never be reached */
421 }
422
423 /*
424 *-----------------------------------------------------------------------------
425 *
426 * Convert --
427 *
428 * Convert a {month, day, year, hours, minutes, seconds, meridian, dst}
429 * tuple into a clock seconds value.
430 *
431 * Results:
432 * 0 or -1 indicating success or failure.
433 *
434 * Side effects:
435 * Fills TimePtr with the computed value.
436 *
437 *-----------------------------------------------------------------------------
438 */
439 static int
440 Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr)
441 time_t Month;
442 time_t Day;
443 time_t Year;
444 time_t Hours;
445 time_t Minutes;
446 time_t Seconds;
447 MERIDIAN Meridian;
448 DSTMODE DSTmode;
449 time_t *TimePtr;
450 {
451 static int DaysInMonth[12] = {
452 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
453 };
454 time_t tod;
455 time_t Julian;
456 int i;
457
458 /* Figure out how many days are in February for the given year.
459 * Every year divisible by 4 is a leap year.
460 * But, every year divisible by 100 is not a leap year.
461 * But, every year divisible by 400 is a leap year after all.
462 */
463 DaysInMonth[1] = IsLeapYear(Year) ? 29 : 28;
464
465 /* Check the inputs for validity */
466 if (Month < 1 || Month > 12
467 || Year < START_OF_TIME || Year > END_OF_TIME
468 || Day < 1 || Day > DaysInMonth[(int)--Month])
469 return -1;
470
471 /* Start computing the value. First determine the number of days
472 * represented by the date, then multiply by the number of seconds/day.
473 */
474 for (Julian = Day - 1, i = 0; i < Month; i++)
475 Julian += DaysInMonth[i];
476 if (Year >= EPOCH) {
477 for (i = EPOCH; i < Year; i++)
478 Julian += 365 + IsLeapYear(i);
479 } else {
480 for (i = Year; i < EPOCH; i++)
481 Julian -= 365 + IsLeapYear(i);
482 }
483 Julian *= SECSPERDAY;
484
485 /* Add the timezone offset ?? */
486 Julian += TclDateTimezone * 60L;
487
488 /* Add the number of seconds represented by the time component */
489 if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
490 return -1;
491 Julian += tod;
492
493 /* Perform a preliminary DST compensation ?? */
494 if (DSTmode == DSTon
495 || (DSTmode == DSTmaybe && TclpGetDate((TclpTime_t)&Julian, 0)->tm_isdst))
496 Julian -= 60 * 60;
497 *TimePtr = Julian;
498 return 0;
499 }
500
501
502 static time_t
503 DSTcorrect(Start, Future)
504 time_t Start;
505 time_t Future;
506 {
507 time_t StartDay;
508 time_t FutureDay;
509 StartDay = (TclpGetDate((TclpTime_t)&Start, 0)->tm_hour + 1) % 24;
510 FutureDay = (TclpGetDate((TclpTime_t)&Future, 0)->tm_hour + 1) % 24;
511 return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
512 }
513
514
515 static time_t
516 NamedDay(Start, DayOrdinal, DayNumber)
517 time_t Start;
518 time_t DayOrdinal;
519 time_t DayNumber;
520 {
521 struct tm *tm;
522 time_t now;
523
524 now = Start;
525 tm = TclpGetDate((TclpTime_t)&now, 0);
526 now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
527 now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
528 return DSTcorrect(Start, now);
529 }
530
531 static time_t
532 NamedMonth(Start, MonthOrdinal, MonthNumber)
533 time_t Start;
534 time_t MonthOrdinal;
535 time_t MonthNumber;
536 {
537 struct tm *tm;
538 time_t now;
539 int result;
540
541 now = Start;
542 tm = TclpGetDate((TclpTime_t)&now, 0);
543 /* To compute the next n'th month, we use this alg:
544 * add n to year value
545 * if currentMonth < requestedMonth decrement year value by 1 (so that
546 * doing next february from january gives us february of the current year)
547 * set day to 1, time to 0
548 */
549 tm->tm_year += MonthOrdinal;
550 if (tm->tm_mon < MonthNumber - 1) {
551 tm->tm_year--;
552 }
553 result = Convert(MonthNumber, (time_t) 1, tm->tm_year + TM_YEAR_BASE,
554 (time_t) 0, (time_t) 0, (time_t) 0, MER24, DSTmaybe, &now);
555 if (result < 0) {
556 return 0;
557 }
558 return DSTcorrect(Start, now);
559 }
560
561 static int
562 RelativeMonth(Start, RelMonth, TimePtr)
563 time_t Start;
564 time_t RelMonth;
565 time_t *TimePtr;
566 {
567 struct tm *tm;
568 time_t Month;
569 time_t Year;
570 time_t Julian;
571 int result;
572
573 if (RelMonth == 0) {
574 *TimePtr = 0;
575 return 0;
576 }
577 tm = TclpGetDate((TclpTime_t)&Start, 0);
578 Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth;
579 Year = Month / 12;
580 Month = Month % 12 + 1;
581 result = Convert(Month, (time_t) tm->tm_mday, Year,
582 (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
583 MER24, DSTmaybe, &Julian);
584 /*
585 * The following iteration takes into account the case were we jump
586 * into a "short month". Far example, "one month from Jan 31" will
587 * fail because there is no Feb 31. The code below will reduce the
588 * day and try converting the date until we succed or the date equals
589 * 28 (which always works unless the date is bad in another way).
590 */
591
592 while ((result != 0) && (tm->tm_mday > 28)) {
593 tm->tm_mday--;
594 result = Convert(Month, (time_t) tm->tm_mday, Year,
595 (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
596 MER24, DSTmaybe, &Julian);
597 }
598 if (result != 0) {
599 return -1;
600 }
601 *TimePtr = DSTcorrect(Start, Julian);
602 return 0;
603 }
604
605
606 /*
607 *-----------------------------------------------------------------------------
608 *
609 * RelativeDay --
610 *
611 * Given a starting time and a number of days before or after, compute the
612 * DST corrected difference between those dates.
613 *
614 * Results:
615 * 1 or -1 indicating success or failure.
616 *
617 * Side effects:
618 * Fills TimePtr with the computed value.
619 *
620 *-----------------------------------------------------------------------------
621 */
622
623 static int
624 RelativeDay(Start, RelDay, TimePtr)
625 time_t Start;
626 time_t RelDay;
627 time_t *TimePtr;
628 {
629 time_t new;
630
631 new = Start + (RelDay * 60 * 60 * 24);
632 *TimePtr = DSTcorrect(Start, new);
633 return 1;
634 }
635
636 static int
637 LookupWord(buff)
638 char *buff;
639 {
640 register char *p;
641 register char *q;
642 register TABLE *tp;
643 int i;
644 int abbrev;
645
646 /*
647 * Make it lowercase.
648 */
649
650 Tcl_UtfToLower(buff);
651
652 if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
653 TclDatelval.Meridian = MERam;
654 return tMERIDIAN;
655 }
656 if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
657 TclDatelval.Meridian = MERpm;
658 return tMERIDIAN;
659 }
660
661 /*
662 * See if we have an abbreviation for a month.
663 */
664 if (strlen(buff) == 3) {
665 abbrev = 1;
666 } else if (strlen(buff) == 4 && buff[3] == '.') {
667 abbrev = 1;
668 buff[3] = '\0';
669 } else {
670 abbrev = 0;
671 }
672
673 for (tp = MonthDayTable; tp->name; tp++) {
674 if (abbrev) {
675 if (strncmp(buff, tp->name, 3) == 0) {
676 TclDatelval.Number = tp->value;
677 return tp->type;
678 }
679 } else if (strcmp(buff, tp->name) == 0) {
680 TclDatelval.Number = tp->value;
681 return tp->type;
682 }
683 }
684
685 for (tp = TimezoneTable; tp->name; tp++) {
686 if (strcmp(buff, tp->name) == 0) {
687 TclDatelval.Number = tp->value;
688 return tp->type;
689 }
690 }
691
692 for (tp = UnitsTable; tp->name; tp++) {
693 if (strcmp(buff, tp->name) == 0) {
694 TclDatelval.Number = tp->value;
695 return tp->type;
696 }
697 }
698
699 /*
700 * Strip off any plural and try the units table again.
701 */
702 i = strlen(buff) - 1;
703 if (buff[i] == 's') {
704 buff[i] = '\0';
705 for (tp = UnitsTable; tp->name; tp++) {
706 if (strcmp(buff, tp->name) == 0) {
707 TclDatelval.Number = tp->value;
708 return tp->type;
709 }
710 }
711 }
712
713 for (tp = OtherTable; tp->name; tp++) {
714 if (strcmp(buff, tp->name) == 0) {
715 TclDatelval.Number = tp->value;
716 return tp->type;
717 }
718 }
719
720 /*
721 * Military timezones.
722 */
723 if (buff[1] == '\0' && !(*buff & 0x80)
724 && isalpha(UCHAR(*buff))) { /* INTL: ISO only */
725 for (tp = MilitaryTable; tp->name; tp++) {
726 if (strcmp(buff, tp->name) == 0) {
727 TclDatelval.Number = tp->value;
728 return tp->type;
729 }
730 }
731 }
732
733 /*
734 * Drop out any periods and try the timezone table again.
735 */
736 for (i = 0, p = q = buff; *q; q++)
737 if (*q != '.') {
738 *p++ = *q;
739 } else {
740 i++;
741 }
742 *p = '\0';
743 if (i) {
744 for (tp = TimezoneTable; tp->name; tp++) {
745 if (strcmp(buff, tp->name) == 0) {
746 TclDatelval.Number = tp->value;
747 return tp->type;
748 }
749 }
750 }
751
752 return tID;
753 }
754
755
756 static int
757 TclDatelex()
758 {
759 register char c;
760 register char *p;
761 char buff[20];
762 int Count;
763
764 for ( ; ; ) {
765 while (isspace(UCHAR(*TclDateInput))) {
766 TclDateInput++;
767 }
768
769 if (isdigit(UCHAR(c = *TclDateInput))) { /* INTL: digit */
770 /* convert the string into a number; count the number of digits */
771 Count = 0;
772 for (TclDatelval.Number = 0;
773 isdigit(UCHAR(c = *TclDateInput++)); ) { /* INTL: digit */
774 TclDatelval.Number = 10 * TclDatelval.Number + c - '0';
775 Count++;
776 }
777 TclDateInput--;
778 /* A number with 6 or more digits is considered an ISO 8601 base */
779 if (Count >= 6) {
780 return tISOBASE;
781 } else {
782 return tUNUMBER;
783 }
784 }
785 if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
786 for (p = buff; isalpha(UCHAR(c = *TclDateInput++)) /* INTL: ISO only. */
787 || c == '.'; ) {
788 if (p < &buff[sizeof buff - 1]) {
789 *p++ = c;
790 }
791 }
792 *p = '\0';
793 TclDateInput--;
794 return LookupWord(buff);
795 }
796 if (c != '(') {
797 return *TclDateInput++;
798 }
799 Count = 0;
800 do {
801 c = *TclDateInput++;
802 if (c == '\0') {
803 return c;
804 } else if (c == '(') {
805 Count++;
806 } else if (c == ')') {
807 Count--;
808 }
809 } while (Count > 0);
810 }
811 }
812
813 /*
814 * Specify zone is of -50000 to force GMT. (This allows BST to work).
815 */
816
817 int
818 TclGetDate(p, now, zone, timePtr)
819 char *p;
820 unsigned long now;
821 long zone;
822 unsigned long *timePtr;
823 {
824 struct tm *tm;
825 time_t Start;
826 time_t Time;
827 time_t tod;
828 int thisyear;
829
830 TclDateInput = p;
831 /* now has to be cast to a time_t for 64bit compliance */
832 Start = now;
833 tm = TclpGetDate((TclpTime_t) &Start, 0);
834 thisyear = tm->tm_year + TM_YEAR_BASE;
835 TclDateYear = thisyear;
836 TclDateMonth = tm->tm_mon + 1;
837 TclDateDay = tm->tm_mday;
838 TclDateTimezone = zone;
839 if (zone == -50000) {
840 TclDateDSTmode = DSToff; /* assume GMT */
841 TclDateTimezone = 0;
842 } else {
843 TclDateDSTmode = DSTmaybe;
844 }
845 TclDateHour = 0;
846 TclDateMinutes = 0;
847 TclDateSeconds = 0;
848 TclDateMeridian = MER24;
849 TclDateRelSeconds = 0;
850 TclDateRelMonth = 0;
851 TclDateRelDay = 0;
852 TclDateRelPointer = NULL;
853
854 TclDateHaveDate = 0;
855 TclDateHaveDay = 0;
856 TclDateHaveOrdinalMonth = 0;
857 TclDateHaveRel = 0;
858 TclDateHaveTime = 0;
859 TclDateHaveZone = 0;
860
861 if (TclDateparse() || TclDateHaveTime > 1 || TclDateHaveZone > 1 || TclDateHaveDate > 1 ||
862 TclDateHaveDay > 1 || TclDateHaveOrdinalMonth > 1) {
863 return -1;
864 }
865
866 if (TclDateHaveDate || TclDateHaveTime || TclDateHaveDay) {
867 if (TclDateYear < 0) {
868 TclDateYear = -TclDateYear;
869 }
870 /*
871 * The following line handles years that are specified using
872 * only two digits. The line of code below implements a policy
873 * defined by the X/Open workgroup on the millinium rollover.
874 * Note: some of those dates may not actually be valid on some
875 * platforms. The POSIX standard startes that the dates 70-99
876 * shall refer to 1970-1999 and 00-38 shall refer to 2000-2038.
877 * This later definition should work on all platforms.
878 */
879
880 if (TclDateYear < 100) {
881 if (TclDateYear >= 69) {
882 TclDateYear += 1900;
883 } else {
884 TclDateYear += 2000;
885 }
886 }
887 if (Convert(TclDateMonth, TclDateDay, TclDateYear, TclDateHour, TclDateMinutes, TclDateSeconds,
888 TclDateMeridian, TclDateDSTmode, &Start) < 0) {
889 return -1;
890 }
891 } else {
892 Start = now;
893 if (!TclDateHaveRel) {
894 Start -= ((tm->tm_hour * 60L * 60L) +
895 tm->tm_min * 60L) + tm->tm_sec;
896 }
897 }
898
899 Start += TclDateRelSeconds;
900 if (RelativeMonth(Start, TclDateRelMonth, &Time) < 0) {
901 return -1;
902 }
903 Start += Time;
904
905 if (RelativeDay(Start, TclDateRelDay, &Time) < 0) {
906 return -1;
907 }
908 Start += Time;
909
910 if (TclDateHaveDay && !TclDateHaveDate) {
911 tod = NamedDay(Start, TclDateDayOrdinal, TclDateDayNumber);
912 Start += tod;
913 }
914
915 if (TclDateHaveOrdinalMonth) {
916 tod = NamedMonth(Start, TclDateMonthOrdinal, TclDateMonth);
917 Start += tod;
918 }
919
920 *timePtr = Start;
921 return 0;
922 }
923 static CONST TclDatetabelem TclDateexca[] ={
924 -1, 1,
925 0, -1,
926 -2, 0,
927 };
928 # define YYNPROD 56
929 # define YYLAST 261
930 static CONST TclDatetabelem TclDateact[]={
931
932 24, 39, 23, 35, 55, 83, 40, 27, 54, 25,
933 36, 41, 59, 37, 57, 27, 26, 25, 27, 32,
934 25, 31, 62, 50, 26, 82, 78, 26, 51, 77,
935 76, 75, 29, 74, 73, 72, 70, 52, 49, 48,
936 47, 44, 38, 63, 80, 46, 45, 81, 69, 21,
937 66, 61, 68, 67, 56, 43, 64, 11, 10, 9,
938 8, 7, 34, 6, 5, 4, 3, 2, 42, 1,
939 20, 0, 0, 0, 0, 0, 0, 0, 0, 0,
940 0, 53, 0, 0, 0, 0, 0, 0, 0, 0,
941 0, 58, 0, 0, 60, 0, 0, 79, 0, 0,
942 0, 0, 0, 0, 0, 0, 0, 71, 0, 0,
943 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
944 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
945 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
946 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
947 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
948 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
949 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
950 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
951 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
952 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
953 0, 0, 0, 0, 0, 19, 14, 0, 0, 0,
954 16, 27, 22, 25, 0, 12, 13, 17, 0, 15,
955 26, 18, 30, 0, 0, 28, 0, 33, 27, 0,
956 25, 0, 0, 0, 0, 0, 0, 26, 0, 0,
957 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,
958 65 };
959 static CONST TclDatetabelem TclDatepact[]={
960
961 -10000000, -43,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,
962 -10000000,-10000000, -26, -268,-10000000, -259, -226,-10000000, -257, 11,
963 -227, -212, -228,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000, -229,
964 -10000000, -230, -240, -231, -212,-10000000, -264,-10000000, 10,-10000000,
965 -10000000, -249,-10000000,-10000000, -246,-10000000,-10000000, 5, -2, 3,
966 8, 7,-10000000,-10000000,-10000000, -10, -232,-10000000,-10000000,-10000000,
967 -212, -233,-10000000, -234, -235,-10000000, -237, -238, -239, -242,
968 -10000000,-10000000,-10000000,-10000000, -1,-10000000,-10000000,-10000000, -11,-10000000,
969 -243, -263,-10000000,-10000000 };
970 static CONST TclDatetabelem TclDatepgo[]={
971
972 0, 49, 46, 70, 22, 69, 67, 66, 65, 64,
973 63, 61, 60, 59, 58, 57 };
974 static CONST TclDatetabelem TclDater1[]={
975
976 0, 5, 5, 6, 6, 6, 6, 6, 6, 6,
977 6, 6, 7, 7, 7, 7, 7, 8, 8, 8,
978 11, 11, 11, 11, 11, 9, 9, 9, 9, 9,
979 9, 9, 9, 9, 9, 10, 10, 13, 13, 13,
980 14, 12, 12, 12, 12, 12, 3, 3, 1, 1,
981 1, 2, 2, 15, 4, 4 };
982 static CONST TclDatetabelem TclDater2[]={
983
984 0, 0, 4, 3, 3, 3, 3, 3, 3, 3,
985 3, 2, 5, 9, 11, 13, 15, 5, 3, 3,
986 3, 5, 5, 7, 5, 7, 11, 3, 11, 11,
987 5, 9, 5, 3, 7, 5, 7, 7, 15, 5,
988 9, 9, 7, 5, 7, 5, 3, 3, 3, 3,
989 3, 3, 1, 3, 1, 3 };
990 static CONST TclDatetabelem TclDatechk[]={
991
992 -10000000, -5, -6, -7, -8, -9, -10, -11, -12, -13,
993 -14, -15, 268, 269, 259, 272, 263, 270, 274, 258,
994 -3, -1, 265, 45, 43, 266, 273, 264, 261, 58,
995 258, 47, 45, 263, -1, 271, 269, 272, 268, 258,
996 263, 268, -1, 44, 268, -2, 257, 268, 268, 268,
997 263, 268, 268, -2, 272, 268, 44, 263, -1, 258,
998 -1, 46, -4, 45, 58, 261, 47, 45, 45, 58,
999 268, -2, 268, 268, 268, 268, 268, 268, 268, -4,
1000 45, 58, 268, 268 };
1001 static CONST TclDatetabelem TclDatedef[]={
1002
1003 1, -2, 2, 3, 4, 5, 6, 7, 8, 9,
1004 10, 11, 53, 18, 19, 27, 0, 33, 0, 20,
1005 0, 52, 0, 46, 47, 48, 49, 50, 12, 0,
1006 22, 0, 0, 32, 52, 17, 0, 39, 30, 24,
1007 35, 0, 43, 21, 0, 45, 51, 0, 54, 25,
1008 0, 0, 34, 42, 37, 0, 0, 36, 44, 23,
1009 52, 0, 13, 0, 0, 55, 0, 0, 0, 0,
1010 31, 41, 40, 14, 54, 26, 28, 29, 0, 15,
1011 0, 0, 16, 38 };
1012 typedef struct
1013 #ifdef __cplusplus
1014 TclDatetoktype
1015 #endif
1016 { char *t_name; int t_val; } TclDatetoktype;
1017 #ifndef YYDEBUG
1018 # define YYDEBUG 0 /* don't allow debugging */
1019 #endif
1020
1021 #if YYDEBUG
1022
1023 TclDatetoktype TclDatetoks[] =
1024 {
1025 "tAGO", 257,
1026 "tDAY", 258,
1027 "tDAYZONE", 259,
1028 "tID", 260,
1029 "tMERIDIAN", 261,
1030 "tMINUTE_UNIT", 262,
1031 "tMONTH", 263,
1032 "tMONTH_UNIT", 264,
1033 "tSTARDATE", 265,
1034 "tSEC_UNIT", 266,
1035 "tSNUMBER", 267,
1036 "tUNUMBER", 268,
1037 "tZONE", 269,
1038 "tEPOCH", 270,
1039 "tDST", 271,
1040 "tISOBASE", 272,
1041 "tDAY_UNIT", 273,
1042 "tNEXT", 274,
1043 "-unknown-", -1 /* ends search */
1044 };
1045
1046 char * TclDatereds[] =
1047 {
1048 "-no such reduction-",
1049 "spec : /* empty */",
1050 "spec : spec item",
1051 "item : time",
1052 "item : zone",
1053 "item : date",
1054 "item : ordMonth",
1055 "item : day",
1056 "item : relspec",
1057 "item : iso",
1058 "item : trek",
1059 "item : number",
1060 "time : tUNUMBER tMERIDIAN",
1061 "time : tUNUMBER ':' tUNUMBER o_merid",
1062 "time : tUNUMBER ':' tUNUMBER '-' tUNUMBER",
1063 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
1064 "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER",
1065 "zone : tZONE tDST",
1066 "zone : tZONE",
1067 "zone : tDAYZONE",
1068 "day : tDAY",
1069 "day : tDAY ','",
1070 "day : tUNUMBER tDAY",
1071 "day : sign tUNUMBER tDAY",
1072 "day : tNEXT tDAY",
1073 "date : tUNUMBER '/' tUNUMBER",
1074 "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
1075 "date : tISOBASE",
1076 "date : tUNUMBER '-' tMONTH '-' tUNUMBER",
1077 "date : tUNUMBER '-' tUNUMBER '-' tUNUMBER",
1078 "date : tMONTH tUNUMBER",
1079 "date : tMONTH tUNUMBER ',' tUNUMBER",
1080 "date : tUNUMBER tMONTH",
1081 "date : tEPOCH",
1082 "date : tUNUMBER tMONTH tUNUMBER",
1083 "ordMonth : tNEXT tMONTH",
1084 "ordMonth : tNEXT tUNUMBER tMONTH",
1085 "iso : tISOBASE tZONE tISOBASE",
1086 "iso : tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER",
1087 "iso : tISOBASE tISOBASE",
1088 "trek : tSTARDATE tUNUMBER '.' tUNUMBER",
1089 "relspec : sign tUNUMBER unit ago",
1090 "relspec : tUNUMBER unit ago",
1091 "relspec : tNEXT unit",
1092 "relspec : tNEXT tUNUMBER unit",
1093 "relspec : unit ago",
1094 "sign : '-'",
1095 "sign : '+'",
1096 "unit : tSEC_UNIT",
1097 "unit : tDAY_UNIT",
1098 "unit : tMONTH_UNIT",
1099 "ago : tAGO",
1100 "ago : /* empty */",
1101 "number : tUNUMBER",
1102 "o_merid : /* empty */",
1103 "o_merid : tMERIDIAN",
1104 };
1105 #endif /* YYDEBUG */
1106 /*
1107 * Copyright (c) 1993 by Sun Microsystems, Inc.
1108 */
1109
1110
1111 /*
1112 ** Skeleton parser driver for yacc output
1113 */
1114
1115 /*
1116 ** yacc user known macros and defines
1117 */
1118 #define YYERROR goto TclDateerrlab
1119 #define YYACCEPT return(0)
1120 #define YYABORT return(1)
1121 #define YYBACKUP( newtoken, newvalue )\
1122 {\
1123 if ( TclDatechar >= 0 || ( TclDater2[ TclDatetmp ] >> 1 ) != 1 )\
1124 {\
1125 TclDateerror( "syntax error - cannot backup" );\
1126 goto TclDateerrlab;\
1127 }\
1128 TclDatechar = newtoken;\
1129 TclDatestate = *TclDateps;\
1130 TclDatelval = newvalue;\
1131 goto TclDatenewstate;\
1132 }
1133 #define YYRECOVERING() (!!TclDateerrflag)
1134 #define YYNEW(type) malloc(sizeof(type) * TclDatenewmax)
1135 #define YYCOPY(to, from, type) \
1136 (type *) memcpy(to, (char *) from, TclDatemaxdepth * sizeof (type))
1137 #define YYENLARGE( from, type) \
1138 (type *) realloc((char *) from, TclDatenewmax * sizeof(type))
1139 #ifndef YYDEBUG
1140 # define YYDEBUG 1 /* make debugging available */
1141 #endif
1142
1143 /*
1144 ** user known globals
1145 */
1146 int TclDatedebug; /* set to 1 to get debugging */
1147
1148 /*
1149 ** driver internal defines
1150 */
1151 #define YYFLAG (-10000000)
1152
1153 /*
1154 ** global variables used by the parser
1155 */
1156 YYSTYPE *TclDatepv; /* top of value stack */
1157 int *TclDateps; /* top of state stack */
1158
1159 int TclDatestate; /* current state */
1160 int TclDatetmp; /* extra var (lasts between blocks) */
1161
1162 int TclDatenerrs; /* number of errors */
1163 int TclDateerrflag; /* error recovery flag */
1164 int TclDatechar; /* current input token number */
1165
1166
1167
1168 #ifdef YYNMBCHARS
1169 #define YYLEX() TclDatecvtok(TclDatelex())
1170 /*
1171 ** TclDatecvtok - return a token if i is a wchar_t value that exceeds 255.
1172 ** If i<255, i itself is the token. If i>255 but the neither
1173 ** of the 30th or 31st bit is on, i is already a token.
1174 */
1175 #if defined(__STDC__) || defined(__cplusplus)
1176 int TclDatecvtok(int i)
1177 #else
1178 int TclDatecvtok(i) int i;
1179 #endif
1180 {
1181 int first = 0;
1182 int last = YYNMBCHARS - 1;
1183 int mid;
1184 wchar_t j;
1185
1186 if(i&0x60000000){/*Must convert to a token. */
1187 if( TclDatembchars[last].character < i ){
1188 return i;/*Giving up*/
1189 }
1190 while ((last>=first)&&(first>=0)) {/*Binary search loop*/
1191 mid = (first+last)/2;
1192 j = TclDatembchars[mid].character;
1193 if( j==i ){/*Found*/
1194 return TclDatembchars[mid].tvalue;
1195 }else if( j<i ){
1196 first = mid + 1;
1197 }else{
1198 last = mid -1;
1199 }
1200 }
1201 /*No entry in the table.*/
1202 return i;/* Giving up.*/
1203 }else{/* i is already a token. */
1204 return i;
1205 }
1206 }
1207 #else/*!YYNMBCHARS*/
1208 #define YYLEX() TclDatelex()
1209 #endif/*!YYNMBCHARS*/
1210
1211 /*
1212 ** TclDateparse - return 0 if worked, 1 if syntax error not recovered from
1213 */
1214 #if defined(__STDC__) || defined(__cplusplus)
1215 int TclDateparse(void)
1216 #else
1217 int TclDateparse()
1218 #endif
1219 {
1220 register YYSTYPE *TclDatepvt = 0; /* top of value stack for $vars */
1221
1222 #if defined(__cplusplus) || defined(lint)
1223 /*
1224 hacks to please C++ and lint - goto's inside
1225 switch should never be executed
1226 */
1227 static int __yaccpar_lint_hack__ = 0;
1228 switch (__yaccpar_lint_hack__)
1229 {
1230 case 1: goto TclDateerrlab;
1231 case 2: goto TclDatenewstate;
1232 }
1233 #endif
1234
1235 /*
1236 ** Initialize externals - TclDateparse may be called more than once
1237 */
1238 TclDatepv = &TclDatev[-1];
1239 TclDateps = &TclDates[-1];
1240 TclDatestate = 0;
1241 TclDatetmp = 0;
1242 TclDatenerrs = 0;
1243 TclDateerrflag = 0;
1244 TclDatechar = -1;
1245
1246 #if YYMAXDEPTH <= 0
1247 if (TclDatemaxdepth <= 0)
1248 {
1249 if ((TclDatemaxdepth = YYEXPAND(0)) <= 0)
1250 {
1251 TclDateerror("yacc initialization error");
1252 YYABORT;
1253 }
1254 }
1255 #endif
1256
1257 {
1258 register YYSTYPE *TclDate_pv; /* top of value stack */
1259 register int *TclDate_ps; /* top of state stack */
1260 register int TclDate_state; /* current state */
1261 register int TclDate_n; /* internal state number info */
1262 goto TclDatestack; /* moved from 6 lines above to here to please C++ */
1263
1264 /*
1265 ** get globals into registers.
1266 ** branch to here only if YYBACKUP was called.
1267 */
1268 TclDate_pv = TclDatepv;
1269 TclDate_ps = TclDateps;
1270 TclDate_state = TclDatestate;
1271 goto TclDate_newstate;
1272
1273 /*
1274 ** get globals into registers.
1275 ** either we just started, or we just finished a reduction
1276 */
1277 TclDatestack:
1278 TclDate_pv = TclDatepv;
1279 TclDate_ps = TclDateps;
1280 TclDate_state = TclDatestate;
1281
1282 /*
1283 ** top of for (;;) loop while no reductions done
1284 */
1285 TclDate_stack:
1286 /*
1287 ** put a state and value onto the stacks
1288 */
1289 #if YYDEBUG
1290 /*
1291 ** if debugging, look up token value in list of value vs.
1292 ** name pairs. 0 and negative (-1) are special values.
1293 ** Note: linear search is used since time is not a real
1294 ** consideration while debugging.
1295 */
1296 if ( TclDatedebug )
1297 {
1298 register int TclDate_i;
1299
1300 printf( "State %d, token ", TclDate_state );
1301 if ( TclDatechar == 0 )
1302 printf( "end-of-file\n" );
1303 else if ( TclDatechar < 0 )
1304 printf( "-none-\n" );
1305 else
1306 {
1307 for ( TclDate_i = 0; TclDatetoks[TclDate_i].t_val >= 0;
1308 TclDate_i++ )
1309 {
1310 if ( TclDatetoks[TclDate_i].t_val == TclDatechar )
1311 break;
1312 }
1313 printf( "%s\n", TclDatetoks[TclDate_i].t_name );
1314 }
1315 }
1316 #endif /* YYDEBUG */
1317 if ( ++TclDate_ps >= &TclDates[ TclDatemaxdepth ] ) /* room on stack? */
1318 {
1319 /*
1320 ** reallocate and recover. Note that pointers
1321 ** have to be reset, or bad things will happen
1322 */
1323 long TclDateps_index = (TclDate_ps - TclDates);
1324 long TclDatepv_index = (TclDate_pv - TclDatev);
1325 long TclDatepvt_index = (TclDatepvt - TclDatev);
1326 int TclDatenewmax;
1327 #ifdef YYEXPAND
1328 TclDatenewmax = YYEXPAND(TclDatemaxdepth);
1329 #else
1330 TclDatenewmax = 2 * TclDatemaxdepth; /* double table size */
1331 if (TclDatemaxdepth == YYMAXDEPTH) /* first time growth */
1332 {
1333 char *newTclDates = (char *)YYNEW(int);
1334 char *newTclDatev = (char *)YYNEW(YYSTYPE);
1335 if (newTclDates != 0 && newTclDatev != 0)
1336 {
1337 TclDates = YYCOPY(newTclDates, TclDates, int);
1338 TclDatev = YYCOPY(newTclDatev, TclDatev, YYSTYPE);
1339 }
1340 else
1341 TclDatenewmax = 0; /* failed */
1342 }
1343 else /* not first time */
1344 {
1345 TclDates = YYENLARGE(TclDates, int);
1346 TclDatev = YYENLARGE(TclDatev, YYSTYPE);
1347 if (TclDates == 0 || TclDatev == 0)
1348 TclDatenewmax = 0; /* failed */
1349 }
1350 #endif
1351 if (TclDatenewmax <= TclDatemaxdepth) /* tables not expanded */
1352 {
1353 TclDateerror( "yacc stack overflow" );
1354 YYABORT;
1355 }
1356 TclDatemaxdepth = TclDatenewmax;
1357
1358 TclDate_ps = TclDates + TclDateps_index;
1359 TclDate_pv = TclDatev + TclDatepv_index;
1360 TclDatepvt = TclDatev + TclDatepvt_index;
1361 }
1362 *TclDate_ps = TclDate_state;
1363 *++TclDate_pv = TclDateval;
1364
1365 /*
1366 ** we have a new state - find out what to do
1367 */
1368 TclDate_newstate:
1369 if ( ( TclDate_n = TclDatepact[ TclDate_state ] ) <= YYFLAG )
1370 goto TclDatedefault; /* simple state */
1371 #if YYDEBUG
1372 /*
1373 ** if debugging, need to mark whether new token grabbed
1374 */
1375 TclDatetmp = TclDatechar < 0;
1376 #endif
1377 if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) )
1378 TclDatechar = 0; /* reached EOF */
1379 #if YYDEBUG
1380 if ( TclDatedebug && TclDatetmp )
1381 {
1382 register int TclDate_i;
1383
1384 printf( "Received token " );
1385 if ( TclDatechar == 0 )
1386 printf( "end-of-file\n" );
1387 else if ( TclDatechar < 0 )
1388 printf( "-none-\n" );
1389 else
1390 {
1391 for ( TclDate_i = 0; TclDatetoks[TclDate_i].t_val >= 0;
1392 TclDate_i++ )
1393 {
1394 if ( TclDatetoks[TclDate_i].t_val == TclDatechar )
1395 break;
1396 }
1397 printf( "%s\n", TclDatetoks[TclDate_i].t_name );
1398 }
1399 }
1400 #endif /* YYDEBUG */
1401 if ( ( ( TclDate_n += TclDatechar ) < 0 ) || ( TclDate_n >= YYLAST ) )
1402 goto TclDatedefault;
1403 if ( TclDatechk[ TclDate_n = TclDateact[ TclDate_n ] ] == TclDatechar ) /*valid shift*/
1404 {
1405 TclDatechar = -1;
1406 TclDateval = TclDatelval;
1407 TclDate_state = TclDate_n;
1408 if ( TclDateerrflag > 0 )
1409 TclDateerrflag--;
1410 goto TclDate_stack;
1411 }
1412
1413 TclDatedefault:
1414 if ( ( TclDate_n = TclDatedef[ TclDate_state ] ) == -2 )
1415 {
1416 #if YYDEBUG
1417 TclDatetmp = TclDatechar < 0;
1418 #endif
1419 if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) )
1420 TclDatechar = 0; /* reached EOF */
1421 #if YYDEBUG
1422 if ( TclDatedebug && TclDatetmp )
1423 {
1424 register int TclDate_i;
1425
1426 printf( "Received token " );
1427 if ( TclDatechar == 0 )
1428 printf( "end-of-file\n" );
1429 else if ( TclDatechar < 0 )
1430 printf( "-none-\n" );
1431 else
1432 {
1433 for ( TclDate_i = 0;
1434 TclDatetoks[TclDate_i].t_val >= 0;
1435 TclDate_i++ )
1436 {
1437 if ( TclDatetoks[TclDate_i].t_val
1438 == TclDatechar )
1439 {
1440 break;
1441 }
1442 }
1443 printf( "%s\n", TclDatetoks[TclDate_i].t_name );
1444 }
1445 }
1446 #endif /* YYDEBUG */
1447 /*
1448 ** look through exception table
1449 */
1450 {
1451 register CONST int *TclDatexi = TclDateexca;
1452
1453 while ( ( *TclDatexi != -1 ) ||
1454 ( TclDatexi[1] != TclDate_state ) )
1455 {
1456 TclDatexi += 2;
1457 }
1458 while ( ( *(TclDatexi += 2) >= 0 ) &&
1459 ( *TclDatexi != TclDatechar ) )
1460 ;
1461 if ( ( TclDate_n = TclDatexi[1] ) < 0 )
1462 YYACCEPT;
1463 }
1464 }
1465
1466 /*
1467 ** check for syntax error
1468 */
1469 if ( TclDate_n == 0 ) /* have an error */
1470 {
1471 /* no worry about speed here! */
1472 switch ( TclDateerrflag )
1473 {
1474 case 0: /* new error */
1475 TclDateerror( "syntax error" );
1476 goto skip_init;
1477 /*
1478 ** get globals into registers.
1479 ** we have a user generated syntax type error
1480 */
1481 TclDate_pv = TclDatepv;
1482 TclDate_ps = TclDateps;
1483 TclDate_state = TclDatestate;
1484 skip_init:
1485 TclDatenerrs++;
1486 /* FALLTHRU */
1487 case 1:
1488 case 2: /* incompletely recovered error */
1489 /* try again... */
1490 TclDateerrflag = 3;
1491 /*
1492 ** find state where "error" is a legal
1493 ** shift action
1494 */
1495 while ( TclDate_ps >= TclDates )
1496 {
1497 TclDate_n = TclDatepact[ *TclDate_ps ] + YYERRCODE;
1498 if ( TclDate_n >= 0 && TclDate_n < YYLAST &&
1499 TclDatechk[TclDateact[TclDate_n]] == YYERRCODE) {
1500 /*
1501 ** simulate shift of "error"
1502 */
1503 TclDate_state = TclDateact[ TclDate_n ];
1504 goto TclDate_stack;
1505 }
1506 /*
1507 ** current state has no shift on
1508 ** "error", pop stack
1509 */
1510 #if YYDEBUG
1511 # define _POP_ "Error recovery pops state %d, uncovers state %d\n"
1512 if ( TclDatedebug )
1513 printf( _POP_, *TclDate_ps,
1514 TclDate_ps[-1] );
1515 # undef _POP_
1516 #endif
1517 TclDate_ps--;
1518 TclDate_pv--;
1519 }
1520 /*
1521 ** there is no state on stack with "error" as
1522 ** a valid shift. give up.
1523 */
1524 YYABORT;
1525 case 3: /* no shift yet; eat a token */
1526 #if YYDEBUG
1527 /*
1528 ** if debugging, look up token in list of
1529 ** pairs. 0 and negative shouldn't occur,
1530 ** but since timing doesn't matter when
1531 ** debugging, it doesn't hurt to leave the
1532 ** tests here.
1533 */
1534 if ( TclDatedebug )
1535 {
1536 register int TclDate_i;
1537
1538 printf( "Error recovery discards " );
1539 if ( TclDatechar == 0 )
1540 printf( "token end-of-file\n" );
1541 else if ( TclDatechar < 0 )
1542 printf( "token -none-\n" );
1543 else
1544 {
1545 for ( TclDate_i = 0;
1546 TclDatetoks[TclDate_i].t_val >= 0;
1547 TclDate_i++ )
1548 {
1549 if ( TclDatetoks[TclDate_i].t_val
1550 == TclDatechar )
1551 {
1552 break;
1553 }
1554 }
1555 printf( "token %s\n",
1556 TclDatetoks[TclDate_i].t_name );
1557 }
1558 }
1559 #endif /* YYDEBUG */
1560 if ( TclDatechar == 0 ) /* reached EOF. quit */
1561 YYABORT;
1562 TclDatechar = -1;
1563 goto TclDate_newstate;
1564 }
1565 }/* end if ( TclDate_n == 0 ) */
1566 /*
1567 ** reduction by production TclDate_n
1568 ** put stack tops, etc. so things right after switch
1569 */
1570 #if YYDEBUG
1571 /*
1572 ** if debugging, print the string that is the user's
1573 ** specification of the reduction which is just about
1574 ** to be done.
1575 */
1576 if ( TclDatedebug )
1577 printf( "Reduce by (%d) \"%s\"\n",
1578 TclDate_n, TclDatereds[ TclDate_n ] );
1579 #endif
1580 TclDatetmp = TclDate_n; /* value to switch over */
1581 TclDatepvt = TclDate_pv; /* $vars top of value stack */
1582 /*
1583 ** Look in goto table for next state
1584 ** Sorry about using TclDate_state here as temporary
1585 ** register variable, but why not, if it works...
1586 ** If TclDater2[ TclDate_n ] doesn't have the low order bit
1587 ** set, then there is no action to be done for
1588 ** this reduction. So, no saving & unsaving of
1589 ** registers done. The only difference between the
1590 ** code just after the if and the body of the if is
1591 ** the goto TclDate_stack in the body. This way the test
1592 ** can be made before the choice of what to do is needed.
1593 */
1594 {
1595 /* length of production doubled with extra bit */
1596 register int TclDate_len = TclDater2[ TclDate_n ];
1597
1598 if ( !( TclDate_len & 01 ) )
1599 {
1600 TclDate_len >>= 1;
1601 TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */
1602 TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] +
1603 *( TclDate_ps -= TclDate_len ) + 1;
1604 if ( TclDate_state >= YYLAST ||
1605 TclDatechk[ TclDate_state =
1606 TclDateact[ TclDate_state ] ] != -TclDate_n )
1607 {
1608 TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ];
1609 }
1610 goto TclDate_stack;
1611 }
1612 TclDate_len >>= 1;
1613 TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */
1614 TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] +
1615 *( TclDate_ps -= TclDate_len ) + 1;
1616 if ( TclDate_state >= YYLAST ||
1617 TclDatechk[ TclDate_state = TclDateact[ TclDate_state ] ] != -TclDate_n )
1618 {
1619 TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ];
1620 }
1621 }
1622 /* save until reenter driver code */
1623 TclDatestate = TclDate_state;
1624 TclDateps = TclDate_ps;
1625 TclDatepv = TclDate_pv;
1626 }
1627 /*
1628 ** code supplied by user is placed in this switch
1629 */
1630 switch( TclDatetmp )
1631 {
1632
1633 case 3:{
1634 TclDateHaveTime++;
1635 } break;
1636 case 4:{
1637 TclDateHaveZone++;
1638 } break;
1639 case 5:{
1640 TclDateHaveDate++;
1641 } break;
1642 case 6:{
1643 TclDateHaveOrdinalMonth++;
1644 } break;
1645 case 7:{
1646 TclDateHaveDay++;
1647 } break;
1648 case 8:{
1649 TclDateHaveRel++;
1650 } break;
1651 case 9:{
1652 TclDateHaveTime++;
1653 TclDateHaveDate++;
1654 } break;
1655 case 10:{
1656 TclDateHaveTime++;
1657 TclDateHaveDate++;
1658 TclDateHaveRel++;
1659 } break;
1660 case 12:{
1661 TclDateHour = TclDatepvt[-1].Number;
1662 TclDateMinutes = 0;
1663 TclDateSeconds = 0;
1664 TclDateMeridian = TclDatepvt[-0].Meridian;
1665 } break;
1666 case 13:{
1667 TclDateHour = TclDatepvt[-3].Number;
1668 TclDateMinutes = TclDatepvt[-1].Number;
1669 TclDateSeconds = 0;
1670 TclDateMeridian = TclDatepvt[-0].Meridian;
1671 } break;
1672 case 14:{
1673 TclDateHour = TclDatepvt[-4].Number;
1674 TclDateMinutes = TclDatepvt[-2].Number;
1675 TclDateMeridian = MER24;
1676 TclDateDSTmode = DSToff;
1677 TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60);
1678 } break;
1679 case 15:{
1680 TclDateHour = TclDatepvt[-5].Number;
1681 TclDateMinutes = TclDatepvt[-3].Number;
1682 TclDateSeconds = TclDatepvt[-1].Number;
1683 TclDateMeridian = TclDatepvt[-0].Meridian;
1684 } break;
1685 case 16:{
1686 TclDateHour = TclDatepvt[-6].Number;
1687 TclDateMinutes = TclDatepvt[-4].Number;
1688 TclDateSeconds = TclDatepvt[-2].Number;
1689 TclDateMeridian = MER24;
1690 TclDateDSTmode = DSToff;
1691 TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60);
1692 } break;
1693 case 17:{
1694 TclDateTimezone = TclDatepvt[-1].Number;
1695 TclDateDSTmode = DSTon;
1696 } break;
1697 case 18:{
1698 TclDateTimezone = TclDatepvt[-0].Number;
1699 TclDateDSTmode = DSToff;
1700 } break;
1701 case 19:{
1702 TclDateTimezone = TclDatepvt[-0].Number;
1703 TclDateDSTmode = DSTon;
1704 } break;
1705 case 20:{
1706 TclDateDayOrdinal = 1;
1707 TclDateDayNumber = TclDatepvt[-0].Number;
1708 } break;
1709 case 21:{
1710 TclDateDayOrdinal = 1;
1711 TclDateDayNumber = TclDatepvt[-1].Number;
1712 } break;
1713 case 22:{
1714 TclDateDayOrdinal = TclDatepvt[-1].Number;
1715 TclDateDayNumber = TclDatepvt[-0].Number;
1716 } break;
1717 case 23:{
1718 TclDateDayOrdinal = TclDatepvt[-2].Number * TclDatepvt[-1].Number;
1719 TclDateDayNumber = TclDatepvt[-0].Number;
1720 } break;
1721 case 24:{
1722 TclDateDayOrdinal = 2;
1723 TclDateDayNumber = TclDatepvt[-0].Number;
1724 } break;
1725 case 25:{
1726 TclDateMonth = TclDatepvt[-2].Number;
1727 TclDateDay = TclDatepvt[-0].Number;
1728 } break;
1729 case 26:{
1730 TclDateMonth = TclDatepvt[-4].Number;
1731 TclDateDay = TclDatepvt[-2].Number;
1732 TclDateYear = TclDatepvt[-0].Number;
1733 } break;
1734 case 27:{
1735 TclDateYear = TclDatepvt[-0].Number / 10000;
1736 TclDateMonth = (TclDatepvt[-0].Number % 10000)/100;
1737 TclDateDay = TclDatepvt[-0].Number % 100;
1738 } break;
1739 case 28:{
1740 TclDateDay = TclDatepvt[-4].Number;
1741 TclDateMonth = TclDatepvt[-2].Number;
1742 TclDateYear = TclDatepvt[-0].Number;
1743 } break;
1744 case 29:{
1745 TclDateMonth = TclDatepvt[-2].Number;
1746 TclDateDay = TclDatepvt[-0].Number;
1747 TclDateYear = TclDatepvt[-4].Number;
1748 } break;
1749 case 30:{
1750 TclDateMonth = TclDatepvt[-1].Number;
1751 TclDateDay = TclDatepvt[-0].Number;
1752 } break;
1753 case 31:{
1754 TclDateMonth = TclDatepvt[-3].Number;
1755 TclDateDay = TclDatepvt[-2].Number;
1756 TclDateYear = TclDatepvt[-0].Number;
1757 } break;
1758 case 32:{
1759 TclDateMonth = TclDatepvt[-0].Number;
1760 TclDateDay = TclDatepvt[-1].Number;
1761 } break;
1762 case 33:{
1763 TclDateMonth = 1;
1764 TclDateDay = 1;
1765 TclDateYear = EPOCH;
1766 } break;
1767 case 34:{
1768 TclDateMonth = TclDatepvt[-1].Number;
1769 TclDateDay = TclDatepvt[-2].Number;
1770 TclDateYear = TclDatepvt[-0].Number;
1771 } break;
1772 case 35:{
1773 TclDateMonthOrdinal = 1;
1774 TclDateMonth = TclDatepvt[-0].Number;
1775 } break;
1776 case 36:{
1777 TclDateMonthOrdinal = TclDatepvt[-1].Number;
1778 TclDateMonth = TclDatepvt[-0].Number;
1779 } break;
1780 case 37:{
1781 if (TclDatepvt[-1].Number != HOUR(- 7)) YYABORT;
1782 TclDateYear = TclDatepvt[-2].Number / 10000;
1783 TclDateMonth = (TclDatepvt[-2].Number % 10000)/100;
1784 TclDateDay = TclDatepvt[-2].Number % 100;
1785 TclDateHour = TclDatepvt[-0].Number / 10000;
1786 TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100;
1787 TclDateSeconds = TclDatepvt[-0].Number % 100;
1788 } break;
1789 case 38:{
1790 if (TclDatepvt[-5].Number != HOUR(- 7)) YYABORT;
1791 TclDateYear = TclDatepvt[-6].Number / 10000;
1792 TclDateMonth = (TclDatepvt[-6].Number % 10000)/100;
1793 TclDateDay = TclDatepvt[-6].Number % 100;
1794 TclDateHour = TclDatepvt[-4].Number;
1795 TclDateMinutes = TclDatepvt[-2].Number;
1796 TclDateSeconds = TclDatepvt[-0].Number;
1797 } break;
1798 case 39:{
1799 TclDateYear = TclDatepvt[-1].Number / 10000;
1800 TclDateMonth = (TclDatepvt[-1].Number % 10000)/100;
1801 TclDateDay = TclDatepvt[-1].Number % 100;
1802 TclDateHour = TclDatepvt[-0].Number / 10000;
1803 TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100;
1804 TclDateSeconds = TclDatepvt[-0].Number % 100;
1805 } break;
1806 case 40:{
1807 /*
1808 * Offset computed year by -377 so that the returned years will
1809 * be in a range accessible with a 32 bit clock seconds value
1810 */
1811 TclDateYear = TclDatepvt[-2].Number/1000 + 2323 - 377;
1812 TclDateDay = 1;
1813 TclDateMonth = 1;
1814 TclDateRelDay += ((TclDatepvt[-2].Number%1000)*(365 + IsLeapYear(TclDateYear)))/1000;
1815 TclDateRelSeconds += TclDatepvt[-0].Number * 144 * 60;
1816 } break;
1817 case 41:{ *TclDateRelPointer += TclDatepvt[-3].Number * TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
1818 case 42:{ *TclDateRelPointer += TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
1819 case 43:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break;
1820 case 44:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
1821 case 45:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
1822 case 46:{ TclDateval.Number = -1; } break;
1823 case 47:{ TclDateval.Number = 1; } break;
1824 case 48:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelSeconds; } break;
1825 case 49:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelDay; } break;
1826 case 50:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelMonth; } break;
1827 case 51:{ TclDateval.Number = -1; } break;
1828 case 52:{ TclDateval.Number = 1; } break;
1829 case 53:{
1830 if (TclDateHaveTime && TclDateHaveDate && !TclDateHaveRel) {
1831 TclDateYear = TclDatepvt[-0].Number;
1832 } else {
1833 TclDateHaveTime++;
1834 if (TclDatepvt[-0].Number < 100) {
1835 TclDateHour = TclDatepvt[-0].Number;
1836 TclDateMinutes = 0;
1837 } else {
1838 TclDateHour = TclDatepvt[-0].Number / 100;
1839 TclDateMinutes = TclDatepvt[-0].Number % 100;
1840 }
1841 TclDateSeconds = 0;
1842 TclDateMeridian = MER24;
1843 }
1844 } break;
1845 case 54:{
1846 TclDateval.Meridian = MER24;
1847 } break;
1848 case 55:{
1849 TclDateval.Meridian = TclDatepvt[-0].Meridian;
1850 } break;
1851 }
1852 goto TclDatestack; /* reset registers in driver code */
1853 }
1854
1855
1856 /* $History: tcldate.c $
1857 *
1858 * ***************** Version 1 *****************
1859 * User: Dtashley Date: 1/02/01 Time: 1:27a
1860 * Created in $/IjuScripter, IjuConsole/Source/Tcl Base
1861 * Initial check-in.
1862 */
1863
1864 /* End of TCLDATE.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25