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