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