OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [generic/] [tclDate.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
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
 * RCS: @(#) $Id: tclDate.c,v 1.1.1.1 2002-01-16 10:25:26 markom Exp $
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     TclDateerror _ANSI_ARGS_((char *s));
98
static time_t   ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes,
99
                    time_t Seconds, MERIDIAN Meridian));
100
static int      Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year,
101
                    time_t Hours, time_t Minutes, time_t Seconds,
102
                    MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr));
103
static time_t   DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future));
104
static time_t   RelativeDate _ANSI_ARGS_((time_t Start, time_t DayOrdinal,
105
                    time_t DayNumber));
106
static int      RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth,
107
                    time_t *TimePtr));
108
static int      LookupWord _ANSI_ARGS_((char *buff));
109
static int      TclDatelex _ANSI_ARGS_((void));
110
 
111
int
112
TclDateparse _ANSI_ARGS_((void));
113
typedef union
114
#ifdef __cplusplus
115
        YYSTYPE
116
#endif
117
 {
118
    time_t              Number;
119
    enum _MERIDIAN      Meridian;
120
} YYSTYPE;
121
# define tAGO 257
122
# define tDAY 258
123
# define tDAYZONE 259
124
# define tID 260
125
# define tMERIDIAN 261
126
# define tMINUTE_UNIT 262
127
# define tMONTH 263
128
# define tMONTH_UNIT 264
129
# define tSEC_UNIT 265
130
# define tSNUMBER 266
131
# define tUNUMBER 267
132
# define tZONE 268
133
# define tEPOCH 269
134
# define tDST 270
135
 
136
 
137
 
138
#ifdef __cplusplus
139
 
140
#ifndef TclDateerror
141
        void TclDateerror(const char *);
142
#endif
143
 
144
#ifndef TclDatelex
145
#ifdef __EXTERN_C__
146
        extern "C" { int TclDatelex(void); }
147
#else
148
        int TclDatelex(void);
149
#endif
150
#endif
151
        int TclDateparse(void);
152
 
153
#endif
154
#define TclDateclearin TclDatechar = -1
155
#define TclDateerrok TclDateerrflag = 0
156
extern int TclDatechar;
157
extern int TclDateerrflag;
158
YYSTYPE TclDatelval;
159
YYSTYPE TclDateval;
160
typedef int TclDatetabelem;
161
#ifndef YYMAXDEPTH
162
#define YYMAXDEPTH 150
163
#endif
164
#if YYMAXDEPTH > 0
165
int TclDate_TclDates[YYMAXDEPTH], *TclDates = TclDate_TclDates;
166
YYSTYPE TclDate_TclDatev[YYMAXDEPTH], *TclDatev = TclDate_TclDatev;
167
#else   /* user does initial allocation */
168
int *TclDates;
169
YYSTYPE *TclDatev;
170
#endif
171
static int TclDatemaxdepth = YYMAXDEPTH;
172
# define YYERRCODE 256
173
 
174
 
175
/*
176
 * Month and day table.
177
 */
178
static TABLE    MonthDayTable[] = {
179
    { "january",        tMONTH,  1 },
180
    { "february",       tMONTH,  2 },
181
    { "march",          tMONTH,  3 },
182
    { "april",          tMONTH,  4 },
183
    { "may",            tMONTH,  5 },
184
    { "june",           tMONTH,  6 },
185
    { "july",           tMONTH,  7 },
186
    { "august",         tMONTH,  8 },
187
    { "september",      tMONTH,  9 },
188
    { "sept",           tMONTH,  9 },
189
    { "october",        tMONTH, 10 },
190
    { "november",       tMONTH, 11 },
191
    { "december",       tMONTH, 12 },
192
    { "sunday",         tDAY, 0 },
193
    { "monday",         tDAY, 1 },
194
    { "tuesday",        tDAY, 2 },
195
    { "tues",           tDAY, 2 },
196
    { "wednesday",      tDAY, 3 },
197
    { "wednes",         tDAY, 3 },
198
    { "thursday",       tDAY, 4 },
199
    { "thur",           tDAY, 4 },
200
    { "thurs",          tDAY, 4 },
201
    { "friday",         tDAY, 5 },
202
    { "saturday",       tDAY, 6 },
203
    { NULL }
204
};
205
 
206
/*
207
 * Time units table.
208
 */
209
static TABLE    UnitsTable[] = {
210
    { "year",           tMONTH_UNIT,    12 },
211
    { "month",          tMONTH_UNIT,    1 },
212
    { "fortnight",      tMINUTE_UNIT,   14 * 24 * 60 },
213
    { "week",           tMINUTE_UNIT,   7 * 24 * 60 },
214
    { "day",            tMINUTE_UNIT,   1 * 24 * 60 },
215
    { "hour",           tMINUTE_UNIT,   60 },
216
    { "minute",         tMINUTE_UNIT,   1 },
217
    { "min",            tMINUTE_UNIT,   1 },
218
    { "second",         tSEC_UNIT,      1 },
219
    { "sec",            tSEC_UNIT,      1 },
220
    { NULL }
221
};
222
 
223
/*
224
 * Assorted relative-time words.
225
 */
226
static TABLE    OtherTable[] = {
227
    { "tomorrow",       tMINUTE_UNIT,   1 * 24 * 60 },
228
    { "yesterday",      tMINUTE_UNIT,   -1 * 24 * 60 },
229
    { "today",          tMINUTE_UNIT,   0 },
230
    { "now",            tMINUTE_UNIT,   0 },
231
    { "last",           tUNUMBER,       -1 },
232
    { "this",           tMINUTE_UNIT,   0 },
233
    { "next",           tUNUMBER,       2 },
234
#if 0
235
    { "first",          tUNUMBER,       1 },
236
/*  { "second",         tUNUMBER,       2 }, */
237
    { "third",          tUNUMBER,       3 },
238
    { "fourth",         tUNUMBER,       4 },
239
    { "fifth",          tUNUMBER,       5 },
240
    { "sixth",          tUNUMBER,       6 },
241
    { "seventh",        tUNUMBER,       7 },
242
    { "eighth",         tUNUMBER,       8 },
243
    { "ninth",          tUNUMBER,       9 },
244
    { "tenth",          tUNUMBER,       10 },
245
    { "eleventh",       tUNUMBER,       11 },
246
    { "twelfth",        tUNUMBER,       12 },
247
#endif
248
    { "ago",            tAGO,   1 },
249
    { "epoch",          tEPOCH,   0 },
250
    { NULL }
251
};
252
 
253
/*
254
 * The timezone table.  (Note: This table was modified to not use any floating
255
 * point constants to work around an SGI compiler bug).
256
 */
257
static TABLE    TimezoneTable[] = {
258
    { "gmt",    tZONE,     HOUR( 0) },      /* Greenwich Mean */
259
    { "ut",     tZONE,     HOUR( 0) },      /* Universal (Coordinated) */
260
    { "utc",    tZONE,     HOUR( 0) },
261
    { "wet",    tZONE,     HOUR( 0) } ,     /* Western European */
262
    { "bst",    tDAYZONE,  HOUR( 0) },      /* British Summer */
263
    { "wat",    tZONE,     HOUR( 1) },      /* West Africa */
264
    { "at",     tZONE,     HOUR( 2) },      /* Azores */
265
#if     0
266
    /* For completeness.  BST is also British Summer, and GST is
267
     * also Guam Standard. */
268
    { "bst",    tZONE,     HOUR( 3) },      /* Brazil Standard */
269
    { "gst",    tZONE,     HOUR( 3) },      /* Greenland Standard */
270
#endif
271
    { "nft",    tZONE,     HOUR( 7/2) },    /* Newfoundland */
272
    { "nst",    tZONE,     HOUR( 7/2) },    /* Newfoundland Standard */
273
    { "ndt",    tDAYZONE,  HOUR( 7/2) },    /* Newfoundland Daylight */
274
    { "ast",    tZONE,     HOUR( 4) },      /* Atlantic Standard */
275
    { "adt",    tDAYZONE,  HOUR( 4) },      /* Atlantic Daylight */
276
    { "est",    tZONE,     HOUR( 5) },      /* Eastern Standard */
277
    { "edt",    tDAYZONE,  HOUR( 5) },      /* Eastern Daylight */
278
    { "cst",    tZONE,     HOUR( 6) },      /* Central Standard */
279
    { "cdt",    tDAYZONE,  HOUR( 6) },      /* Central Daylight */
280
    { "mst",    tZONE,     HOUR( 7) },      /* Mountain Standard */
281
    { "mdt",    tDAYZONE,  HOUR( 7) },      /* Mountain Daylight */
282
    { "pst",    tZONE,     HOUR( 8) },      /* Pacific Standard */
283
    { "pdt",    tDAYZONE,  HOUR( 8) },      /* Pacific Daylight */
284
    { "yst",    tZONE,     HOUR( 9) },      /* Yukon Standard */
285
    { "ydt",    tDAYZONE,  HOUR( 9) },      /* Yukon Daylight */
286
    { "hst",    tZONE,     HOUR(10) },      /* Hawaii Standard */
287
    { "hdt",    tDAYZONE,  HOUR(10) },      /* Hawaii Daylight */
288
    { "cat",    tZONE,     HOUR(10) },      /* Central Alaska */
289
    { "ahst",   tZONE,     HOUR(10) },      /* Alaska-Hawaii Standard */
290
    { "nt",     tZONE,     HOUR(11) },      /* Nome */
291
    { "idlw",   tZONE,     HOUR(12) },      /* International Date Line West */
292
    { "cet",    tZONE,    -HOUR( 1) },      /* Central European */
293
    { "met",    tZONE,    -HOUR( 1) },      /* Middle European */
294
    { "mewt",   tZONE,    -HOUR( 1) },      /* Middle European Winter */
295
    { "mest",   tDAYZONE, -HOUR( 1) },      /* Middle European Summer */
296
    { "swt",    tZONE,    -HOUR( 1) },      /* Swedish Winter */
297
    { "sst",    tDAYZONE, -HOUR( 1) },      /* Swedish Summer */
298
    { "fwt",    tZONE,    -HOUR( 1) },      /* French Winter */
299
    { "fst",    tDAYZONE, -HOUR( 1) },      /* French Summer */
300
    { "eet",    tZONE,    -HOUR( 2) },      /* Eastern Europe, USSR Zone 1 */
301
    { "bt",     tZONE,    -HOUR( 3) },      /* Baghdad, USSR Zone 2 */
302
    { "it",     tZONE,    -HOUR( 7/2) },    /* Iran */
303
    { "zp4",    tZONE,    -HOUR( 4) },      /* USSR Zone 3 */
304
    { "zp5",    tZONE,    -HOUR( 5) },      /* USSR Zone 4 */
305
    { "ist",    tZONE,    -HOUR(11/2) },    /* Indian Standard */
306
    { "zp6",    tZONE,    -HOUR( 6) },      /* USSR Zone 5 */
307
#if     0
308
    /* For completeness.  NST is also Newfoundland Stanard, nad SST is
309
     * also Swedish Summer. */
310
    { "nst",    tZONE,    -HOUR(13/2) },    /* North Sumatra */
311
    { "sst",    tZONE,    -HOUR( 7) },      /* South Sumatra, USSR Zone 6 */
312
#endif  /* 0 */
313
    { "wast",   tZONE,    -HOUR( 7) },      /* West Australian Standard */
314
    { "wadt",   tDAYZONE, -HOUR( 7) },      /* West Australian Daylight */
315
    { "jt",     tZONE,    -HOUR(15/2) },    /* Java (3pm in Cronusland!) */
316
    { "cct",    tZONE,    -HOUR( 8) },      /* China Coast, USSR Zone 7 */
317
    { "jst",    tZONE,    -HOUR( 9) },      /* Japan Standard, USSR Zone 8 */
318
    { "cast",   tZONE,    -HOUR(19/2) },    /* Central Australian Standard */
319
    { "cadt",   tDAYZONE, -HOUR(19/2) },    /* Central Australian Daylight */
320
    { "east",   tZONE,    -HOUR(10) },      /* Eastern Australian Standard */
321
    { "eadt",   tDAYZONE, -HOUR(10) },      /* Eastern Australian Daylight */
322
    { "gst",    tZONE,    -HOUR(10) },      /* Guam Standard, USSR Zone 9 */
323
    { "nzt",    tZONE,    -HOUR(12) },      /* New Zealand */
324
    { "nzst",   tZONE,    -HOUR(12) },      /* New Zealand Standard */
325
    { "nzdt",   tDAYZONE, -HOUR(12) },      /* New Zealand Daylight */
326
    { "idle",   tZONE,    -HOUR(12) },      /* International Date Line East */
327
    /* ADDED BY Marco Nijdam */
328
    { "dst",    tDST,     HOUR( 0) },       /* DST on (hour is ignored) */
329
    /* End ADDED */
330
    {  NULL  }
331
};
332
 
333
/*
334
 * Military timezone table.
335
 */
336
static TABLE    MilitaryTable[] = {
337
    { "a",      tZONE,  HOUR(  1) },
338
    { "b",      tZONE,  HOUR(  2) },
339
    { "c",      tZONE,  HOUR(  3) },
340
    { "d",      tZONE,  HOUR(  4) },
341
    { "e",      tZONE,  HOUR(  5) },
342
    { "f",      tZONE,  HOUR(  6) },
343
    { "g",      tZONE,  HOUR(  7) },
344
    { "h",      tZONE,  HOUR(  8) },
345
    { "i",      tZONE,  HOUR(  9) },
346
    { "k",      tZONE,  HOUR( 10) },
347
    { "l",      tZONE,  HOUR( 11) },
348
    { "m",      tZONE,  HOUR( 12) },
349
    { "n",      tZONE,  HOUR(- 1) },
350
    { "o",      tZONE,  HOUR(- 2) },
351
    { "p",      tZONE,  HOUR(- 3) },
352
    { "q",      tZONE,  HOUR(- 4) },
353
    { "r",      tZONE,  HOUR(- 5) },
354
    { "s",      tZONE,  HOUR(- 6) },
355
    { "t",      tZONE,  HOUR(- 7) },
356
    { "u",      tZONE,  HOUR(- 8) },
357
    { "v",      tZONE,  HOUR(- 9) },
358
    { "w",      tZONE,  HOUR(-10) },
359
    { "x",      tZONE,  HOUR(-11) },
360
    { "y",      tZONE,  HOUR(-12) },
361
    { "z",      tZONE,  HOUR(  0) },
362
    { NULL }
363
};
364
 
365
 
366
/*
367
 * Dump error messages in the bit bucket.
368
 */
369
static void
370
TclDateerror(s)
371
    char  *s;
372
{
373
}
374
 
375
 
376
static time_t
377
ToSeconds(Hours, Minutes, Seconds, Meridian)
378
    time_t      Hours;
379
    time_t      Minutes;
380
    time_t      Seconds;
381
    MERIDIAN    Meridian;
382
{
383
    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
384
        return -1;
385
    switch (Meridian) {
386
    case MER24:
387
        if (Hours < 0 || Hours > 23)
388
            return -1;
389
        return (Hours * 60L + Minutes) * 60L + Seconds;
390
    case MERam:
391
        if (Hours < 1 || Hours > 12)
392
            return -1;
393
        return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
394
    case MERpm:
395
        if (Hours < 1 || Hours > 12)
396
            return -1;
397
        return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
398
    }
399
    return -1;  /* Should never be reached */
400
}
401
 
402
 
403
static int
404
Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr)
405
    time_t      Month;
406
    time_t      Day;
407
    time_t      Year;
408
    time_t      Hours;
409
    time_t      Minutes;
410
    time_t      Seconds;
411
    MERIDIAN    Meridian;
412
    DSTMODE     DSTmode;
413
    time_t     *TimePtr;
414
{
415
    static int  DaysInMonth[12] = {
416
        31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
417
    };
418
    time_t tod;
419
    time_t Julian;
420
    int i;
421
 
422
    DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
423
                    ? 29 : 28;
424
    if (Month < 1 || Month > 12
425
     || Year < START_OF_TIME || Year > END_OF_TIME
426
     || Day < 1 || Day > DaysInMonth[(int)--Month])
427
        return -1;
428
 
429
    for (Julian = Day - 1, i = 0; i < Month; i++)
430
        Julian += DaysInMonth[i];
431
    if (Year >= EPOCH) {
432
        for (i = EPOCH; i < Year; i++)
433
            Julian += 365 + (i % 4 == 0);
434
    } else {
435
        for (i = Year; i < EPOCH; i++)
436
            Julian -= 365 + (i % 4 == 0);
437
    }
438
    Julian *= SECSPERDAY;
439
    Julian += TclDateTimezone * 60L;
440
    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
441
        return -1;
442
    Julian += tod;
443
    if (DSTmode == DSTon
444
     || (DSTmode == DSTmaybe && TclpGetDate(&Julian, 0)->tm_isdst))
445
        Julian -= 60 * 60;
446
    *TimePtr = Julian;
447
    return 0;
448
}
449
 
450
 
451
static time_t
452
DSTcorrect(Start, Future)
453
    time_t      Start;
454
    time_t      Future;
455
{
456
    time_t      StartDay;
457
    time_t      FutureDay;
458
 
459
    StartDay = (TclpGetDate(&Start, 0)->tm_hour + 1) % 24;
460
    FutureDay = (TclpGetDate(&Future, 0)->tm_hour + 1) % 24;
461
    return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
462
}
463
 
464
 
465
static time_t
466
RelativeDate(Start, DayOrdinal, DayNumber)
467
    time_t      Start;
468
    time_t      DayOrdinal;
469
    time_t      DayNumber;
470
{
471
    struct tm   *tm;
472
    time_t      now;
473
 
474
    now = Start;
475
    tm = TclpGetDate(&now, 0);
476
    now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
477
    now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
478
    return DSTcorrect(Start, now);
479
}
480
 
481
 
482
static int
483
RelativeMonth(Start, RelMonth, TimePtr)
484
    time_t Start;
485
    time_t RelMonth;
486
    time_t *TimePtr;
487
{
488
    struct tm *tm;
489
    time_t Month;
490
    time_t Year;
491
    time_t Julian;
492
    int result;
493
 
494
    if (RelMonth == 0) {
495
        *TimePtr = 0;
496
        return 0;
497
    }
498
    tm = TclpGetDate(&Start, 0);
499
    Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth;
500
    Year = Month / 12;
501
    Month = Month % 12 + 1;
502
    result = Convert(Month, (time_t) tm->tm_mday, Year,
503
            (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
504
            MER24, DSTmaybe, &Julian);
505
    /*
506
     * The following iteration takes into account the case were we jump
507
     * into a "short month".  Far example, "one month from Jan 31" will
508
     * fail because there is no Feb 31.  The code below will reduce the
509
     * day and try converting the date until we succed or the date equals
510
     * 28 (which always works unless the date is bad in another way).
511
     */
512
 
513
    while ((result != 0) && (tm->tm_mday > 28)) {
514
        tm->tm_mday--;
515
        result = Convert(Month, (time_t) tm->tm_mday, Year,
516
                (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
517
                MER24, DSTmaybe, &Julian);
518
    }
519
    if (result != 0) {
520
        return -1;
521
    }
522
    *TimePtr = DSTcorrect(Start, Julian);
523
    return 0;
524
}
525
 
526
 
527
static int
528
LookupWord(buff)
529
    char                *buff;
530
{
531
    register char *p;
532
    register char *q;
533
    register TABLE *tp;
534
    int i;
535
    int abbrev;
536
 
537
    /*
538
     * Make it lowercase.
539
     */
540
    for (p = buff; *p; p++) {
541
        if (isupper(UCHAR(*p))) {
542
            *p = (char) tolower(UCHAR(*p));
543
        }
544
    }
545
 
546
    if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
547
        TclDatelval.Meridian = MERam;
548
        return tMERIDIAN;
549
    }
550
    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
551
        TclDatelval.Meridian = MERpm;
552
        return tMERIDIAN;
553
    }
554
 
555
    /*
556
     * See if we have an abbreviation for a month.
557
     */
558
    if (strlen(buff) == 3) {
559
        abbrev = 1;
560
    } else if (strlen(buff) == 4 && buff[3] == '.') {
561
        abbrev = 1;
562
        buff[3] = '\0';
563
    } else {
564
        abbrev = 0;
565
    }
566
 
567
    for (tp = MonthDayTable; tp->name; tp++) {
568
        if (abbrev) {
569
            if (strncmp(buff, tp->name, 3) == 0) {
570
                TclDatelval.Number = tp->value;
571
                return tp->type;
572
            }
573
        } else if (strcmp(buff, tp->name) == 0) {
574
            TclDatelval.Number = tp->value;
575
            return tp->type;
576
        }
577
    }
578
 
579
    for (tp = TimezoneTable; tp->name; tp++) {
580
        if (strcmp(buff, tp->name) == 0) {
581
            TclDatelval.Number = tp->value;
582
            return tp->type;
583
        }
584
    }
585
 
586
    for (tp = UnitsTable; tp->name; tp++) {
587
        if (strcmp(buff, tp->name) == 0) {
588
            TclDatelval.Number = tp->value;
589
            return tp->type;
590
        }
591
    }
592
 
593
    /*
594
     * Strip off any plural and try the units table again.
595
     */
596
    i = strlen(buff) - 1;
597
    if (buff[i] == 's') {
598
        buff[i] = '\0';
599
        for (tp = UnitsTable; tp->name; tp++) {
600
            if (strcmp(buff, tp->name) == 0) {
601
                TclDatelval.Number = tp->value;
602
                return tp->type;
603
            }
604
        }
605
    }
606
 
607
    for (tp = OtherTable; tp->name; tp++) {
608
        if (strcmp(buff, tp->name) == 0) {
609
            TclDatelval.Number = tp->value;
610
            return tp->type;
611
        }
612
    }
613
 
614
    /*
615
     * Military timezones.
616
     */
617
    if (buff[1] == '\0' && isalpha(UCHAR(*buff))) {
618
        for (tp = MilitaryTable; tp->name; tp++) {
619
            if (strcmp(buff, tp->name) == 0) {
620
                TclDatelval.Number = tp->value;
621
                return tp->type;
622
            }
623
        }
624
    }
625
 
626
    /*
627
     * Drop out any periods and try the timezone table again.
628
     */
629
    for (i = 0, p = q = buff; *q; q++)
630
        if (*q != '.') {
631
            *p++ = *q;
632
        } else {
633
            i++;
634
        }
635
    *p = '\0';
636
    if (i) {
637
        for (tp = TimezoneTable; tp->name; tp++) {
638
            if (strcmp(buff, tp->name) == 0) {
639
                TclDatelval.Number = tp->value;
640
                return tp->type;
641
            }
642
        }
643
    }
644
 
645
    return tID;
646
}
647
 
648
 
649
static int
650
TclDatelex()
651
{
652
    register char       c;
653
    register char       *p;
654
    char                buff[20];
655
    int                 Count;
656
    int                 sign;
657
 
658
    for ( ; ; ) {
659
        while (isspace((unsigned char) (*TclDateInput))) {
660
            TclDateInput++;
661
        }
662
 
663
        if (isdigit(c = *TclDateInput) || c == '-' || c == '+') {
664
            if (c == '-' || c == '+') {
665
                sign = c == '-' ? -1 : 1;
666
                if (!isdigit(*++TclDateInput)) {
667
                    /*
668
                     * skip the '-' sign
669
                     */
670
                    continue;
671
                }
672
            } else {
673
                sign = 0;
674
            }
675
            for (TclDatelval.Number = 0; isdigit(c = *TclDateInput++); ) {
676
                TclDatelval.Number = 10 * TclDatelval.Number + c - '0';
677
            }
678
            TclDateInput--;
679
            if (sign < 0) {
680
                TclDatelval.Number = -TclDatelval.Number;
681
            }
682
            return sign ? tSNUMBER : tUNUMBER;
683
        }
684
        if (isalpha(UCHAR(c))) {
685
            for (p = buff; isalpha(c = *TclDateInput++) || c == '.'; ) {
686
                if (p < &buff[sizeof buff - 1]) {
687
                    *p++ = c;
688
                }
689
            }
690
            *p = '\0';
691
            TclDateInput--;
692
            return LookupWord(buff);
693
        }
694
        if (c != '(') {
695
            return *TclDateInput++;
696
        }
697
        Count = 0;
698
        do {
699
            c = *TclDateInput++;
700
            if (c == '\0') {
701
                return c;
702
            } else if (c == '(') {
703
                Count++;
704
            } else if (c == ')') {
705
                Count--;
706
            }
707
        } while (Count > 0);
708
    }
709
}
710
 
711
/*
712
 * Specify zone is of -50000 to force GMT.  (This allows BST to work).
713
 */
714
 
715
int
716
TclGetDate(p, now, zone, timePtr)
717
    char *p;
718
    unsigned long now;
719
    long zone;
720
    unsigned long *timePtr;
721
{
722
    struct tm *tm;
723
    time_t Start;
724
    time_t Time;
725
    time_t tod;
726
    int thisyear;
727
 
728
    TclDateInput = p;
729
    tm = TclpGetDate((time_t *) &now, 0);
730
    thisyear = tm->tm_year + TM_YEAR_BASE;
731
    TclDateYear = thisyear;
732
    TclDateMonth = tm->tm_mon + 1;
733
    TclDateDay = tm->tm_mday;
734
    TclDateTimezone = zone;
735
    if (zone == -50000) {
736
        TclDateDSTmode = DSToff;  /* assume GMT */
737
        TclDateTimezone = 0;
738
    } else {
739
        TclDateDSTmode = DSTmaybe;
740
    }
741
    TclDateHour = 0;
742
    TclDateMinutes = 0;
743
    TclDateSeconds = 0;
744
    TclDateMeridian = MER24;
745
    TclDateRelSeconds = 0;
746
    TclDateRelMonth = 0;
747
    TclDateHaveDate = 0;
748
    TclDateHaveDay = 0;
749
    TclDateHaveRel = 0;
750
    TclDateHaveTime = 0;
751
    TclDateHaveZone = 0;
752
 
753
    if (TclDateparse() || TclDateHaveTime > 1 || TclDateHaveZone > 1 || TclDateHaveDate > 1 ||
754
            TclDateHaveDay > 1) {
755
        return -1;
756
    }
757
 
758
    if (TclDateHaveDate || TclDateHaveTime || TclDateHaveDay) {
759
        if (TclDateYear < 0) {
760
            TclDateYear = -TclDateYear;
761
        }
762
        /*
763
         * The following line handles years that are specified using
764
         * only two digits.  The line of code below implements a policy
765
         * defined by the X/Open workgroup on the millinium rollover.
766
         * Note: some of those dates may not actually be valid on some
767
         * platforms.  The POSIX standard startes that the dates 70-99
768
         * shall refer to 1970-1999 and 00-38 shall refer to 2000-2038.
769
         * This later definition should work on all platforms.
770
         */
771
 
772
        if (TclDateYear < 100) {
773
            if (TclDateYear >= 69) {
774
                TclDateYear += 1900;
775
            } else {
776
                TclDateYear += 2000;
777
            }
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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.