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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [insight/] [tcl/] [generic/] [tclGetDate.y] - Blame information for rev 1765

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

Line No. Rev Author Line
1 578 markom
/*
2
 * tclGetDate.y --
3
 *
4
 *      Contains yacc grammar for parsing date and time strings.
5
 *      The output of this file should be the file tclDate.c which
6
 *      is used directly in the Tcl sources.
7
 *
8
 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
9
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
10
 *
11
 * See the file "license.terms" for information on usage and redistribution
12
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
 *
14
 * RCS: @(#) $Id: tclGetDate.y,v 1.1.1.1 2002-01-16 10:25:27 markom Exp $
15
 */
16
 
17
%{
18
/*
19
 * tclDate.c --
20
 *
21
 *      This file is generated from a yacc grammar defined in
22
 *      the file tclGetDate.y.  It should not be edited directly.
23
 *
24
 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
25
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
26
 *
27
 * See the file "license.terms" for information on usage and redistribution
28
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
29
 *
30
 * SCCSID
31
 */
32
 
33
#include "tclInt.h"
34
#include "tclPort.h"
35
 
36
#ifdef MAC_TCL
37
#   define EPOCH           1904
38
#   define START_OF_TIME   1904
39
#   define END_OF_TIME     2039
40
#else
41
#   define EPOCH           1970
42
#   define START_OF_TIME   1902
43
#   define END_OF_TIME     2037
44
#endif
45
 
46
/*
47
 * The offset of tm_year of struct tm returned by localtime, gmtime, etc.
48
 * I don't know how universal this is; K&R II, the NetBSD manpages, and
49
 * ../compat/strftime.c all agree that tm_year is the year-1900.  However,
50
 * some systems may have a different value.  This #define should be the
51
 * same as in ../compat/strftime.c.
52
 */
53
#define TM_YEAR_BASE 1900
54
 
55
#define HOUR(x)         ((int) (60 * x))
56
#define SECSPERDAY      (24L * 60L * 60L)
57
 
58
 
59
/*
60
 *  An entry in the lexical lookup table.
61
 */
62
typedef struct _TABLE {
63
    char        *name;
64
    int         type;
65
    time_t      value;
66
} TABLE;
67
 
68
 
69
/*
70
 *  Daylight-savings mode:  on, off, or not yet known.
71
 */
72
typedef enum _DSTMODE {
73
    DSTon, DSToff, DSTmaybe
74
} DSTMODE;
75
 
76
/*
77
 *  Meridian:  am, pm, or 24-hour style.
78
 */
79
typedef enum _MERIDIAN {
80
    MERam, MERpm, MER24
81
} MERIDIAN;
82
 
83
 
84
/*
85
 *  Global variables.  We could get rid of most of these by using a good
86
 *  union as the yacc stack.  (This routine was originally written before
87
 *  yacc had the %union construct.)  Maybe someday; right now we only use
88
 *  the %union very rarely.
89
 */
90
static char     *yyInput;
91
static DSTMODE  yyDSTmode;
92
static time_t   yyDayOrdinal;
93
static time_t   yyDayNumber;
94
static int      yyHaveDate;
95
static int      yyHaveDay;
96
static int      yyHaveRel;
97
static int      yyHaveTime;
98
static int      yyHaveZone;
99
static time_t   yyTimezone;
100
static time_t   yyDay;
101
static time_t   yyHour;
102
static time_t   yyMinutes;
103
static time_t   yyMonth;
104
static time_t   yySeconds;
105
static time_t   yyYear;
106
static MERIDIAN yyMeridian;
107
static time_t   yyRelMonth;
108
static time_t   yyRelSeconds;
109
 
110
 
111
/*
112
 * Prototypes of internal functions.
113
 */
114
static void     yyerror _ANSI_ARGS_((char *s));
115
static time_t   ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes,
116
                    time_t Seconds, MERIDIAN Meridian));
117
static int      Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year,
118
                    time_t Hours, time_t Minutes, time_t Seconds,
119
                    MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr));
120
static time_t   DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future));
121
static time_t   RelativeDate _ANSI_ARGS_((time_t Start, time_t DayOrdinal,
122
                    time_t DayNumber));
123
static int      RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth,
124
                    time_t *TimePtr));
125
static int      LookupWord _ANSI_ARGS_((char *buff));
126
static int      yylex _ANSI_ARGS_((void));
127
 
128
int
129
yyparse _ANSI_ARGS_((void));
130
%}
131
 
132
%union {
133
    time_t              Number;
134
    enum _MERIDIAN      Meridian;
135
}
136
 
137
%token  tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
138
%token  tSEC_UNIT tSNUMBER tUNUMBER tZONE tEPOCH tDST
139
 
140
%type           tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT tDST
141
%type           tSEC_UNIT tSNUMBER tUNUMBER tZONE
142
%type         tMERIDIAN o_merid
143
 
144
%%
145
 
146
spec    : /* NULL */
147
        | spec item
148
        ;
149
 
150
item    : time {
151
            yyHaveTime++;
152
        }
153
        | zone {
154
            yyHaveZone++;
155
        }
156
        | date {
157
            yyHaveDate++;
158
        }
159
        | day {
160
            yyHaveDay++;
161
        }
162
        | rel {
163
            yyHaveRel++;
164
        }
165
        | number
166
        ;
167
 
168
time    : tUNUMBER tMERIDIAN {
169
            yyHour = $1;
170
            yyMinutes = 0;
171
            yySeconds = 0;
172
            yyMeridian = $2;
173
        }
174
        | tUNUMBER ':' tUNUMBER o_merid {
175
            yyHour = $1;
176
            yyMinutes = $3;
177
            yySeconds = 0;
178
            yyMeridian = $4;
179
        }
180
        | tUNUMBER ':' tUNUMBER tSNUMBER {
181
            yyHour = $1;
182
            yyMinutes = $3;
183
            yyMeridian = MER24;
184
            yyDSTmode = DSToff;
185
            yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
186
        }
187
        | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
188
            yyHour = $1;
189
            yyMinutes = $3;
190
            yySeconds = $5;
191
            yyMeridian = $6;
192
        }
193
        | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
194
            yyHour = $1;
195
            yyMinutes = $3;
196
            yySeconds = $5;
197
            yyMeridian = MER24;
198
            yyDSTmode = DSToff;
199
            yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
200
        }
201
        ;
202
 
203
zone    : tZONE tDST {
204
            yyTimezone = $1;
205
            yyDSTmode = DSTon;
206
        }
207
        | tZONE {
208
            yyTimezone = $1;
209
            yyDSTmode = DSToff;
210
        }
211
        | tDAYZONE {
212
            yyTimezone = $1;
213
            yyDSTmode = DSTon;
214
        }
215
        ;
216
 
217
day     : tDAY {
218
            yyDayOrdinal = 1;
219
            yyDayNumber = $1;
220
        }
221
        | tDAY ',' {
222
            yyDayOrdinal = 1;
223
            yyDayNumber = $1;
224
        }
225
        | tUNUMBER tDAY {
226
            yyDayOrdinal = $1;
227
            yyDayNumber = $2;
228
        }
229
        ;
230
 
231
date    : tUNUMBER '/' tUNUMBER {
232
            yyMonth = $1;
233
            yyDay = $3;
234
        }
235
        | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
236
            yyMonth = $1;
237
            yyDay = $3;
238
            yyYear = $5;
239
        }
240
        | tMONTH tUNUMBER {
241
            yyMonth = $1;
242
            yyDay = $2;
243
        }
244
        | tMONTH tUNUMBER ',' tUNUMBER {
245
            yyMonth = $1;
246
            yyDay = $2;
247
            yyYear = $4;
248
        }
249
        | tUNUMBER tMONTH {
250
            yyMonth = $2;
251
            yyDay = $1;
252
        }
253
                  | tEPOCH {
254
                                yyMonth = 1;
255
                                yyDay = 1;
256
                                yyYear = EPOCH;
257
                  }
258
        | tUNUMBER tMONTH tUNUMBER {
259
            yyMonth = $2;
260
            yyDay = $1;
261
            yyYear = $3;
262
        }
263
        ;
264
 
265
rel     : relunit tAGO {
266
            yyRelSeconds = -yyRelSeconds;
267
            yyRelMonth = -yyRelMonth;
268
        }
269
        | relunit
270
        ;
271
 
272
relunit : tUNUMBER tMINUTE_UNIT {
273
            yyRelSeconds += $1 * $2 * 60L;
274
        }
275
        | tSNUMBER tMINUTE_UNIT {
276
            yyRelSeconds += $1 * $2 * 60L;
277
        }
278
        | tMINUTE_UNIT {
279
            yyRelSeconds += $1 * 60L;
280
        }
281
        | tSNUMBER tSEC_UNIT {
282
            yyRelSeconds += $1;
283
        }
284
        | tUNUMBER tSEC_UNIT {
285
            yyRelSeconds += $1;
286
        }
287
        | tSEC_UNIT {
288
            yyRelSeconds++;
289
        }
290
        | tSNUMBER tMONTH_UNIT {
291
            yyRelMonth += $1 * $2;
292
        }
293
        | tUNUMBER tMONTH_UNIT {
294
            yyRelMonth += $1 * $2;
295
        }
296
        | tMONTH_UNIT {
297
            yyRelMonth += $1;
298
        }
299
        ;
300
 
301
number  : tUNUMBER
302
    {
303
        if (yyHaveTime && yyHaveDate && !yyHaveRel) {
304
            yyYear = $1;
305
        } else {
306
            yyHaveTime++;
307
            if ($1 < 100) {
308
                yyHour = 0;
309
                yyMinutes = $1;
310
            } else {
311
                yyHour = $1 / 100;
312
                yyMinutes = $1 % 100;
313
            }
314
            yySeconds = 0;
315
            yyMeridian = MER24;
316
        }
317
    }
318
;
319
 
320
o_merid : /* NULL */ {
321
            $$ = MER24;
322
        }
323
        | tMERIDIAN {
324
            $$ = $1;
325
        }
326
        ;
327
 
328
%%
329
 
330
/*
331
 * Month and day table.
332
 */
333
static TABLE    MonthDayTable[] = {
334
    { "january",        tMONTH,  1 },
335
    { "february",       tMONTH,  2 },
336
    { "march",          tMONTH,  3 },
337
    { "april",          tMONTH,  4 },
338
    { "may",            tMONTH,  5 },
339
    { "june",           tMONTH,  6 },
340
    { "july",           tMONTH,  7 },
341
    { "august",         tMONTH,  8 },
342
    { "september",      tMONTH,  9 },
343
    { "sept",           tMONTH,  9 },
344
    { "october",        tMONTH, 10 },
345
    { "november",       tMONTH, 11 },
346
    { "december",       tMONTH, 12 },
347
    { "sunday",         tDAY, 0 },
348
    { "monday",         tDAY, 1 },
349
    { "tuesday",        tDAY, 2 },
350
    { "tues",           tDAY, 2 },
351
    { "wednesday",      tDAY, 3 },
352
    { "wednes",         tDAY, 3 },
353
    { "thursday",       tDAY, 4 },
354
    { "thur",           tDAY, 4 },
355
    { "thurs",          tDAY, 4 },
356
    { "friday",         tDAY, 5 },
357
    { "saturday",       tDAY, 6 },
358
    { NULL }
359
};
360
 
361
/*
362
 * Time units table.
363
 */
364
static TABLE    UnitsTable[] = {
365
    { "year",           tMONTH_UNIT,    12 },
366
    { "month",          tMONTH_UNIT,    1 },
367
    { "fortnight",      tMINUTE_UNIT,   14 * 24 * 60 },
368
    { "week",           tMINUTE_UNIT,   7 * 24 * 60 },
369
    { "day",            tMINUTE_UNIT,   1 * 24 * 60 },
370
    { "hour",           tMINUTE_UNIT,   60 },
371
    { "minute",         tMINUTE_UNIT,   1 },
372
    { "min",            tMINUTE_UNIT,   1 },
373
    { "second",         tSEC_UNIT,      1 },
374
    { "sec",            tSEC_UNIT,      1 },
375
    { NULL }
376
};
377
 
378
/*
379
 * Assorted relative-time words.
380
 */
381
static TABLE    OtherTable[] = {
382
    { "tomorrow",       tMINUTE_UNIT,   1 * 24 * 60 },
383
    { "yesterday",      tMINUTE_UNIT,   -1 * 24 * 60 },
384
    { "today",          tMINUTE_UNIT,   0 },
385
    { "now",            tMINUTE_UNIT,   0 },
386
    { "last",           tUNUMBER,       -1 },
387
    { "this",           tMINUTE_UNIT,   0 },
388
    { "next",           tUNUMBER,       2 },
389
#if 0
390
    { "first",          tUNUMBER,       1 },
391
/*  { "second",         tUNUMBER,       2 }, */
392
    { "third",          tUNUMBER,       3 },
393
    { "fourth",         tUNUMBER,       4 },
394
    { "fifth",          tUNUMBER,       5 },
395
    { "sixth",          tUNUMBER,       6 },
396
    { "seventh",        tUNUMBER,       7 },
397
    { "eighth",         tUNUMBER,       8 },
398
    { "ninth",          tUNUMBER,       9 },
399
    { "tenth",          tUNUMBER,       10 },
400
    { "eleventh",       tUNUMBER,       11 },
401
    { "twelfth",        tUNUMBER,       12 },
402
#endif
403
    { "ago",            tAGO,   1 },
404
    { "epoch",          tEPOCH,   0 },
405
    { NULL }
406
};
407
 
408
/*
409
 * The timezone table.  (Note: This table was modified to not use any floating
410
 * point constants to work around an SGI compiler bug).
411
 */
412
static TABLE    TimezoneTable[] = {
413
    { "gmt",    tZONE,     HOUR( 0) },      /* Greenwich Mean */
414
    { "ut",     tZONE,     HOUR( 0) },      /* Universal (Coordinated) */
415
    { "utc",    tZONE,     HOUR( 0) },
416
    { "wet",    tZONE,     HOUR( 0) } ,     /* Western European */
417
    { "bst",    tDAYZONE,  HOUR( 0) },      /* British Summer */
418
    { "wat",    tZONE,     HOUR( 1) },      /* West Africa */
419
    { "at",     tZONE,     HOUR( 2) },      /* Azores */
420
#if     0
421
    /* For completeness.  BST is also British Summer, and GST is
422
     * also Guam Standard. */
423
    { "bst",    tZONE,     HOUR( 3) },      /* Brazil Standard */
424
    { "gst",    tZONE,     HOUR( 3) },      /* Greenland Standard */
425
#endif
426
    { "nft",    tZONE,     HOUR( 7/2) },    /* Newfoundland */
427
    { "nst",    tZONE,     HOUR( 7/2) },    /* Newfoundland Standard */
428
    { "ndt",    tDAYZONE,  HOUR( 7/2) },    /* Newfoundland Daylight */
429
    { "ast",    tZONE,     HOUR( 4) },      /* Atlantic Standard */
430
    { "adt",    tDAYZONE,  HOUR( 4) },      /* Atlantic Daylight */
431
    { "est",    tZONE,     HOUR( 5) },      /* Eastern Standard */
432
    { "edt",    tDAYZONE,  HOUR( 5) },      /* Eastern Daylight */
433
    { "cst",    tZONE,     HOUR( 6) },      /* Central Standard */
434
    { "cdt",    tDAYZONE,  HOUR( 6) },      /* Central Daylight */
435
    { "mst",    tZONE,     HOUR( 7) },      /* Mountain Standard */
436
    { "mdt",    tDAYZONE,  HOUR( 7) },      /* Mountain Daylight */
437
    { "pst",    tZONE,     HOUR( 8) },      /* Pacific Standard */
438
    { "pdt",    tDAYZONE,  HOUR( 8) },      /* Pacific Daylight */
439
    { "yst",    tZONE,     HOUR( 9) },      /* Yukon Standard */
440
    { "ydt",    tDAYZONE,  HOUR( 9) },      /* Yukon Daylight */
441
    { "hst",    tZONE,     HOUR(10) },      /* Hawaii Standard */
442
    { "hdt",    tDAYZONE,  HOUR(10) },      /* Hawaii Daylight */
443
    { "cat",    tZONE,     HOUR(10) },      /* Central Alaska */
444
    { "ahst",   tZONE,     HOUR(10) },      /* Alaska-Hawaii Standard */
445
    { "nt",     tZONE,     HOUR(11) },      /* Nome */
446
    { "idlw",   tZONE,     HOUR(12) },      /* International Date Line West */
447
    { "cet",    tZONE,    -HOUR( 1) },      /* Central European */
448
    { "met",    tZONE,    -HOUR( 1) },      /* Middle European */
449
    { "mewt",   tZONE,    -HOUR( 1) },      /* Middle European Winter */
450
    { "mest",   tDAYZONE, -HOUR( 1) },      /* Middle European Summer */
451
    { "swt",    tZONE,    -HOUR( 1) },      /* Swedish Winter */
452
    { "sst",    tDAYZONE, -HOUR( 1) },      /* Swedish Summer */
453
    { "fwt",    tZONE,    -HOUR( 1) },      /* French Winter */
454
    { "fst",    tDAYZONE, -HOUR( 1) },      /* French Summer */
455
    { "eet",    tZONE,    -HOUR( 2) },      /* Eastern Europe, USSR Zone 1 */
456
    { "bt",     tZONE,    -HOUR( 3) },      /* Baghdad, USSR Zone 2 */
457
    { "it",     tZONE,    -HOUR( 7/2) },    /* Iran */
458
    { "zp4",    tZONE,    -HOUR( 4) },      /* USSR Zone 3 */
459
    { "zp5",    tZONE,    -HOUR( 5) },      /* USSR Zone 4 */
460
    { "ist",    tZONE,    -HOUR(11/2) },    /* Indian Standard */
461
    { "zp6",    tZONE,    -HOUR( 6) },      /* USSR Zone 5 */
462
#if     0
463
    /* For completeness.  NST is also Newfoundland Stanard, nad SST is
464
     * also Swedish Summer. */
465
    { "nst",    tZONE,    -HOUR(13/2) },    /* North Sumatra */
466
    { "sst",    tZONE,    -HOUR( 7) },      /* South Sumatra, USSR Zone 6 */
467
#endif  /* 0 */
468
    { "wast",   tZONE,    -HOUR( 7) },      /* West Australian Standard */
469
    { "wadt",   tDAYZONE, -HOUR( 7) },      /* West Australian Daylight */
470
    { "jt",     tZONE,    -HOUR(15/2) },    /* Java (3pm in Cronusland!) */
471
    { "cct",    tZONE,    -HOUR( 8) },      /* China Coast, USSR Zone 7 */
472
    { "jst",    tZONE,    -HOUR( 9) },      /* Japan Standard, USSR Zone 8 */
473
    { "cast",   tZONE,    -HOUR(19/2) },    /* Central Australian Standard */
474
    { "cadt",   tDAYZONE, -HOUR(19/2) },    /* Central Australian Daylight */
475
    { "east",   tZONE,    -HOUR(10) },      /* Eastern Australian Standard */
476
    { "eadt",   tDAYZONE, -HOUR(10) },      /* Eastern Australian Daylight */
477
    { "gst",    tZONE,    -HOUR(10) },      /* Guam Standard, USSR Zone 9 */
478
    { "nzt",    tZONE,    -HOUR(12) },      /* New Zealand */
479
    { "nzst",   tZONE,    -HOUR(12) },      /* New Zealand Standard */
480
    { "nzdt",   tDAYZONE, -HOUR(12) },      /* New Zealand Daylight */
481
    { "idle",   tZONE,    -HOUR(12) },      /* International Date Line East */
482
    /* ADDED BY Marco Nijdam */
483
    { "dst",    tDST,     HOUR( 0) },       /* DST on (hour is ignored) */
484
    /* End ADDED */
485
    {  NULL  }
486
};
487
 
488
/*
489
 * Military timezone table.
490
 */
491
static TABLE    MilitaryTable[] = {
492
    { "a",      tZONE,  HOUR(  1) },
493
    { "b",      tZONE,  HOUR(  2) },
494
    { "c",      tZONE,  HOUR(  3) },
495
    { "d",      tZONE,  HOUR(  4) },
496
    { "e",      tZONE,  HOUR(  5) },
497
    { "f",      tZONE,  HOUR(  6) },
498
    { "g",      tZONE,  HOUR(  7) },
499
    { "h",      tZONE,  HOUR(  8) },
500
    { "i",      tZONE,  HOUR(  9) },
501
    { "k",      tZONE,  HOUR( 10) },
502
    { "l",      tZONE,  HOUR( 11) },
503
    { "m",      tZONE,  HOUR( 12) },
504
    { "n",      tZONE,  HOUR(- 1) },
505
    { "o",      tZONE,  HOUR(- 2) },
506
    { "p",      tZONE,  HOUR(- 3) },
507
    { "q",      tZONE,  HOUR(- 4) },
508
    { "r",      tZONE,  HOUR(- 5) },
509
    { "s",      tZONE,  HOUR(- 6) },
510
    { "t",      tZONE,  HOUR(- 7) },
511
    { "u",      tZONE,  HOUR(- 8) },
512
    { "v",      tZONE,  HOUR(- 9) },
513
    { "w",      tZONE,  HOUR(-10) },
514
    { "x",      tZONE,  HOUR(-11) },
515
    { "y",      tZONE,  HOUR(-12) },
516
    { "z",      tZONE,  HOUR(  0) },
517
    { NULL }
518
};
519
 
520
 
521
/*
522
 * Dump error messages in the bit bucket.
523
 */
524
static void
525
yyerror(s)
526
    char  *s;
527
{
528
}
529
 
530
 
531
static time_t
532
ToSeconds(Hours, Minutes, Seconds, Meridian)
533
    time_t      Hours;
534
    time_t      Minutes;
535
    time_t      Seconds;
536
    MERIDIAN    Meridian;
537
{
538
    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
539
        return -1;
540
    switch (Meridian) {
541
    case MER24:
542
        if (Hours < 0 || Hours > 23)
543
            return -1;
544
        return (Hours * 60L + Minutes) * 60L + Seconds;
545
    case MERam:
546
        if (Hours < 1 || Hours > 12)
547
            return -1;
548
        return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
549
    case MERpm:
550
        if (Hours < 1 || Hours > 12)
551
            return -1;
552
        return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
553
    }
554
    return -1;  /* Should never be reached */
555
}
556
 
557
 
558
static int
559
Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr)
560
    time_t      Month;
561
    time_t      Day;
562
    time_t      Year;
563
    time_t      Hours;
564
    time_t      Minutes;
565
    time_t      Seconds;
566
    MERIDIAN    Meridian;
567
    DSTMODE     DSTmode;
568
    time_t     *TimePtr;
569
{
570
    static int  DaysInMonth[12] = {
571
        31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
572
    };
573
    time_t tod;
574
    time_t Julian;
575
    int i;
576
 
577
    DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
578
                    ? 29 : 28;
579
    if (Month < 1 || Month > 12
580
     || Year < START_OF_TIME || Year > END_OF_TIME
581
     || Day < 1 || Day > DaysInMonth[(int)--Month])
582
        return -1;
583
 
584
    for (Julian = Day - 1, i = 0; i < Month; i++)
585
        Julian += DaysInMonth[i];
586
    if (Year >= EPOCH) {
587
        for (i = EPOCH; i < Year; i++)
588
            Julian += 365 + (i % 4 == 0);
589
    } else {
590
        for (i = Year; i < EPOCH; i++)
591
            Julian -= 365 + (i % 4 == 0);
592
    }
593
    Julian *= SECSPERDAY;
594
    Julian += yyTimezone * 60L;
595
    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
596
        return -1;
597
    Julian += tod;
598
    if (DSTmode == DSTon
599
     || (DSTmode == DSTmaybe && TclpGetDate(&Julian, 0)->tm_isdst))
600
        Julian -= 60 * 60;
601
    *TimePtr = Julian;
602
    return 0;
603
}
604
 
605
 
606
static time_t
607
DSTcorrect(Start, Future)
608
    time_t      Start;
609
    time_t      Future;
610
{
611
    time_t      StartDay;
612
    time_t      FutureDay;
613
 
614
    StartDay = (TclpGetDate(&Start, 0)->tm_hour + 1) % 24;
615
    FutureDay = (TclpGetDate(&Future, 0)->tm_hour + 1) % 24;
616
    return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
617
}
618
 
619
 
620
static time_t
621
RelativeDate(Start, DayOrdinal, DayNumber)
622
    time_t      Start;
623
    time_t      DayOrdinal;
624
    time_t      DayNumber;
625
{
626
    struct tm   *tm;
627
    time_t      now;
628
 
629
    now = Start;
630
    tm = TclpGetDate(&now, 0);
631
    now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
632
    now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
633
    return DSTcorrect(Start, now);
634
}
635
 
636
 
637
static int
638
RelativeMonth(Start, RelMonth, TimePtr)
639
    time_t Start;
640
    time_t RelMonth;
641
    time_t *TimePtr;
642
{
643
    struct tm *tm;
644
    time_t Month;
645
    time_t Year;
646
    time_t Julian;
647
    int result;
648
 
649
    if (RelMonth == 0) {
650
        *TimePtr = 0;
651
        return 0;
652
    }
653
    tm = TclpGetDate(&Start, 0);
654
    Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth;
655
    Year = Month / 12;
656
    Month = Month % 12 + 1;
657
    result = Convert(Month, (time_t) tm->tm_mday, Year,
658
            (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
659
            MER24, DSTmaybe, &Julian);
660
    /*
661
     * The following iteration takes into account the case were we jump
662
     * into a "short month".  Far example, "one month from Jan 31" will
663
     * fail because there is no Feb 31.  The code below will reduce the
664
     * day and try converting the date until we succed or the date equals
665
     * 28 (which always works unless the date is bad in another way).
666
     */
667
 
668
    while ((result != 0) && (tm->tm_mday > 28)) {
669
        tm->tm_mday--;
670
        result = Convert(Month, (time_t) tm->tm_mday, Year,
671
                (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
672
                MER24, DSTmaybe, &Julian);
673
    }
674
    if (result != 0) {
675
        return -1;
676
    }
677
    *TimePtr = DSTcorrect(Start, Julian);
678
    return 0;
679
}
680
 
681
 
682
static int
683
LookupWord(buff)
684
    char                *buff;
685
{
686
    register char *p;
687
    register char *q;
688
    register TABLE *tp;
689
    int i;
690
    int abbrev;
691
 
692
    /*
693
     * Make it lowercase.
694
     */
695
    for (p = buff; *p; p++) {
696
        if (isupper(UCHAR(*p))) {
697
            *p = (char) tolower(UCHAR(*p));
698
        }
699
    }
700
 
701
    if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
702
        yylval.Meridian = MERam;
703
        return tMERIDIAN;
704
    }
705
    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
706
        yylval.Meridian = MERpm;
707
        return tMERIDIAN;
708
    }
709
 
710
    /*
711
     * See if we have an abbreviation for a month.
712
     */
713
    if (strlen(buff) == 3) {
714
        abbrev = 1;
715
    } else if (strlen(buff) == 4 && buff[3] == '.') {
716
        abbrev = 1;
717
        buff[3] = '\0';
718
    } else {
719
        abbrev = 0;
720
    }
721
 
722
    for (tp = MonthDayTable; tp->name; tp++) {
723
        if (abbrev) {
724
            if (strncmp(buff, tp->name, 3) == 0) {
725
                yylval.Number = tp->value;
726
                return tp->type;
727
            }
728
        } else if (strcmp(buff, tp->name) == 0) {
729
            yylval.Number = tp->value;
730
            return tp->type;
731
        }
732
    }
733
 
734
    for (tp = TimezoneTable; tp->name; tp++) {
735
        if (strcmp(buff, tp->name) == 0) {
736
            yylval.Number = tp->value;
737
            return tp->type;
738
        }
739
    }
740
 
741
    for (tp = UnitsTable; tp->name; tp++) {
742
        if (strcmp(buff, tp->name) == 0) {
743
            yylval.Number = tp->value;
744
            return tp->type;
745
        }
746
    }
747
 
748
    /*
749
     * Strip off any plural and try the units table again.
750
     */
751
    i = strlen(buff) - 1;
752
    if (buff[i] == 's') {
753
        buff[i] = '\0';
754
        for (tp = UnitsTable; tp->name; tp++) {
755
            if (strcmp(buff, tp->name) == 0) {
756
                yylval.Number = tp->value;
757
                return tp->type;
758
            }
759
        }
760
    }
761
 
762
    for (tp = OtherTable; tp->name; tp++) {
763
        if (strcmp(buff, tp->name) == 0) {
764
            yylval.Number = tp->value;
765
            return tp->type;
766
        }
767
    }
768
 
769
    /*
770
     * Military timezones.
771
     */
772
    if (buff[1] == '\0' && isalpha(UCHAR(*buff))) {
773
        for (tp = MilitaryTable; tp->name; tp++) {
774
            if (strcmp(buff, tp->name) == 0) {
775
                yylval.Number = tp->value;
776
                return tp->type;
777
            }
778
        }
779
    }
780
 
781
    /*
782
     * Drop out any periods and try the timezone table again.
783
     */
784
    for (i = 0, p = q = buff; *q; q++)
785
        if (*q != '.') {
786
            *p++ = *q;
787
        } else {
788
            i++;
789
        }
790
    *p = '\0';
791
    if (i) {
792
        for (tp = TimezoneTable; tp->name; tp++) {
793
            if (strcmp(buff, tp->name) == 0) {
794
                yylval.Number = tp->value;
795
                return tp->type;
796
            }
797
        }
798
    }
799
 
800
    return tID;
801
}
802
 
803
 
804
static int
805
yylex()
806
{
807
    register char       c;
808
    register char       *p;
809
    char                buff[20];
810
    int                 Count;
811
    int                 sign;
812
 
813
    for ( ; ; ) {
814
        while (isspace((unsigned char) (*yyInput))) {
815
            yyInput++;
816
        }
817
 
818
        if (isdigit(c = *yyInput) || c == '-' || c == '+') {
819
            if (c == '-' || c == '+') {
820
                sign = c == '-' ? -1 : 1;
821
                if (!isdigit(*++yyInput)) {
822
                    /*
823
                     * skip the '-' sign
824
                     */
825
                    continue;
826
                }
827
            } else {
828
                sign = 0;
829
            }
830
            for (yylval.Number = 0; isdigit(c = *yyInput++); ) {
831
                yylval.Number = 10 * yylval.Number + c - '0';
832
            }
833
            yyInput--;
834
            if (sign < 0) {
835
                yylval.Number = -yylval.Number;
836
            }
837
            return sign ? tSNUMBER : tUNUMBER;
838
        }
839
        if (isalpha(UCHAR(c))) {
840
            for (p = buff; isalpha(c = *yyInput++) || c == '.'; ) {
841
                if (p < &buff[sizeof buff - 1]) {
842
                    *p++ = c;
843
                }
844
            }
845
            *p = '\0';
846
            yyInput--;
847
            return LookupWord(buff);
848
        }
849
        if (c != '(') {
850
            return *yyInput++;
851
        }
852
        Count = 0;
853
        do {
854
            c = *yyInput++;
855
            if (c == '\0') {
856
                return c;
857
            } else if (c == '(') {
858
                Count++;
859
            } else if (c == ')') {
860
                Count--;
861
            }
862
        } while (Count > 0);
863
    }
864
}
865
 
866
/*
867
 * Specify zone is of -50000 to force GMT.  (This allows BST to work).
868
 */
869
 
870
int
871
TclGetDate(p, now, zone, timePtr)
872
    char *p;
873
    unsigned long now;
874
    long zone;
875
    unsigned long *timePtr;
876
{
877
    struct tm *tm;
878
    time_t Start;
879
    time_t Time;
880
    time_t tod;
881
    int thisyear;
882
 
883
    yyInput = p;
884
    tm = TclpGetDate((time_t *) &now, 0);
885
    thisyear = tm->tm_year + TM_YEAR_BASE;
886
    yyYear = thisyear;
887
    yyMonth = tm->tm_mon + 1;
888
    yyDay = tm->tm_mday;
889
    yyTimezone = zone;
890
    if (zone == -50000) {
891
        yyDSTmode = DSToff;  /* assume GMT */
892
        yyTimezone = 0;
893
    } else {
894
        yyDSTmode = DSTmaybe;
895
    }
896
    yyHour = 0;
897
    yyMinutes = 0;
898
    yySeconds = 0;
899
    yyMeridian = MER24;
900
    yyRelSeconds = 0;
901
    yyRelMonth = 0;
902
    yyHaveDate = 0;
903
    yyHaveDay = 0;
904
    yyHaveRel = 0;
905
    yyHaveTime = 0;
906
    yyHaveZone = 0;
907
 
908
    if (yyparse() || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 ||
909
            yyHaveDay > 1) {
910
        return -1;
911
    }
912
 
913
    if (yyHaveDate || yyHaveTime || yyHaveDay) {
914
        if (TclDateYear < 0) {
915
            TclDateYear = -TclDateYear;
916
        }
917
        /*
918
         * The following line handles years that are specified using
919
         * only two digits.  The line of code below implements a policy
920
         * defined by the X/Open workgroup on the millinium rollover.
921
         * Note: some of those dates may not actually be valid on some
922
         * platforms.  The POSIX standard startes that the dates 70-99
923
         * shall refer to 1970-1999 and 00-38 shall refer to 2000-2038.
924
         * This later definition should work on all platforms.
925
         */
926
 
927
        if (TclDateYear < 100) {
928
            if (TclDateYear >= 69) {
929
                TclDateYear += 1900;
930
            } else {
931
                TclDateYear += 2000;
932
            }
933
        }
934
        if (Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
935
                yyMeridian, yyDSTmode, &Start) < 0) {
936
            return -1;
937
        }
938
    } else {
939
        Start = now;
940
        if (!yyHaveRel) {
941
            Start -= ((tm->tm_hour * 60L) + tm->tm_min * 60L) + tm->tm_sec;
942
        }
943
    }
944
 
945
    Start += yyRelSeconds;
946
    if (RelativeMonth(Start, yyRelMonth, &Time) < 0) {
947
        return -1;
948
    }
949
    Start += Time;
950
 
951
    if (yyHaveDay && !yyHaveDate) {
952
        tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
953
        Start += tod;
954
    }
955
 
956
    *timePtr = Start;
957
    return 0;
958
}

powered by: WebSVN 2.1.0

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